Bullet Simulation

Content:
1. The main goal
2. Physics behind the prototype
3. Vertex copying
4. Vertex pushing
5. Forces on the bullet
6. Bullet shapes
7. Wall tearing
8. Accurate bullet physics
9. Bullet deformation
10. Prototype
11. Inaccuracies
12. Conclusion
13. Pictures
14. Sources

1. The main goal
First of all it is useful to define a main goal to work towards in this research, what do i want to achieve or create during this time period. I answered that question by with dividing the end product up into two parts, it could be applicable and useful withing games and to work with later on or it can be as realistic as possible without compromising on performance or how it should be used. For this research i decided to focus more on the physics part of things and to try to get this simulation to run as realistic as i could make it, within the 5 weeks.

This realism would be split into a few parts, these i laid out in order going from very necessary and the more base parts, to the less important and nice to haves in the prototype. First i wanted to make the vertex displacement part, which is the very base of the simulation, an object should be able to push vertices in a wall. Next on the list is the ability for the wall to push and apply forces to the thrown object, with this the bullet will be able to come to a halt and stop deforming the wall. With this the object will also be able to bounce off of the wall and be redirected by it. With this done i can add the ability for the wall to create holes in itself on places where the object could be able to pierce it. Next step would be to make the bullet also deformable, this seemed to be a large task to make but not one with much impact on the overall outcome of the simulation. This would, in theory, also allow for two movable object to hit and deform each other, but this is not focused on within the research.

Lastly I wanted to add the retainment of mass in the wall, which would make sure that all the mass pushed inwards by the thrown object would also be pushed outwards on a different spot on the wall. This part is scrapped because the wall in the simulation is a single sided plane, which does not have a “real” mass.

2. Physics
Before diving into the making of this simulation i first need to explain some of the physics behind it. When an object is moving through a space, it has forces applied to it, a force propelling it forward, and forces trying to slow it down. In the case of our object it has an initial force which is only applied at the beginning moving it forward, it is pushed towards the wall. Usually the force trying to slow it down would be the force of air restriction, like in many physics examples this force can be ignored because it does not have much to do with the impact of the object in the wall.

When the initial force is applied to the moving object, the object is given a certain amount of energy, the kinetic energy. This energy can be calculated by the following formula

Ek = 0.5 * m * v^2

Ek(j) is the kinetic energy in joules
m is the mass of the object in kilograms
v is the velocity of the object in meters per second

As you can see the more velocity or speed you give to the object, the more energy that specific object will have. A fast moving object with a low mass will have more destructive power than a heavy slow moving object.

When the object hits the wall the wall should bend to the shape of the object, this bending also requires energy to do, and since energy cannot be created without a source, the energy should be coming from the only source it could get it from, the moving object. In order to understand this transfer of energy completely it is important to understand the law of conservation of energy. This law states that the total energy in an isolated system should remain the same, and since the unity simulation is an isolated system all the energy created by moving the object should be going somewhere. Some or all of it can be transferred to the wall in order to bend the material, in a real world example however, there is also energy transferred to heat up the metal, this energy is ‘lost’ and will not contribute to the overall simulation in a way which helps visualize the impact of the object. Applying the force of air resistance will only slow the moving object down which limits the ability to get a better control on this impact.

As said earlier, when hitting the wall, most of the energy is transferred to the wall in order to bend it and possibly create holes. However when this energy is transferred to the wall the bullet is losing its kinetic energy, so it is slowed down. Looking back to the formula of the kinetic energy, when the object loses its kinetic energy it either lost weight or velocity. So the bullet has to deform or slowdown in order to give the energy to the wall. In the beginning of making the simulation we will first be assuming that all of the energy which is given to the wall is coming from the velocity of the object, since the bullet deformation is one of the last steps of making the simulation.

Because we now know that the moving object is slowed down (and that mass might be lost by hitting the wall), which is further implied by Newtons first law: An object in motion stays in motion unless acted upon by an unbalanced force, there has to be an external force which slows the moving object down. This force is the normal force of the wall, which is implied by Newtons third law, if object A exerts a force on object B, object B also exerts an equal and opposite force on object A. So if the moving object puts a force onto the wall the wall pushes the bullet back with a force. And because the bullet is moving with a constant speed this so called normal force of the wall will always result in the deceleration of the moving object. The force exerted onto the object by the wall will always be the same as the force put upon that part of the wall by the object.

Normal force explained, normal force is allway away from the face of an object at a 90 degree angle

By using the normal force theory as explained above, it is possible to get the physics correct in some cases. In reality however, the normal force is not allways exactly the force of the moving object. The normal force is the red arrow in the picture above, notice that this force is perpendicular to the red object? This is because the normal force is always perpendicular to its origin or face. Say the red object was not facing the green object like in the picture above but at an angle. Now the force exerted onto the red object is smaller than in the picture above. In the picture below this example is shown. The green arrow is still the same force as in the picture above, but the actual force put onto the red object is smaller, this is caused by the angle the red object is in. The blue arrow is the actual force exerted onto the red object, and the red arrow is the normal force, which still is the same as the force exerted onto the red object.

Normal force explained at an angle

To calculate the normal force in this example is a bit harder than if the angle of attack is at 0 degrees. First thing to calculate is the direction of the blue arrow, for this we can use the cosine function and the length of the green arrow and the direction of the normal vector of the red box (we can get this information from a unity mesh, the length will always be 1). The length of the blue arrow can be calculated as follows:

The triangle seen between the green and blue arrow is a so called right-angled triangle, one of the corners is at a 90 degree angle, see the picture below. This lets us use the cosine function to calculate the angle between the green and blue arrow. We know the blue arrow is the opposite of the red arrow and we know the direction of the red arrow, with unity. We now can safely say that the opposite of the red arrow is the same direction of the blue arrow, so to calculate the angle between the blue and green arrow we can use the unity built in function, Vector3.Angle(), we now have the correct angle. To calculate the correct normal force we have to use the “Cos(angle) = adjacent side / oblique side” function. In this case the adjacent side is the blue arrow and the oblique side the green one. By isolating the adjacent side, which is the blue arrow we get “blue arrow = green arrow * Cos(angle). The final step is to invert this calculated blue arrow to get the correct normal force.

The right-angled triangle in for the example

Before the object can move through or deform the wall we first have to calculate the distance the parts of the wall travel during the deformation, this can be calculated with the work applied to the wall. The formula of which is shown below

W = F * d

W is work in joules
F is the force applied
d is the distance traveled or extended

Work explained (SaveMyExams, 2023)

With this formula we can add the energy given to us by the bullet as calculated by the removal of speed by the normal forces applied by the wall. As stated earlier on in the research we will first be focusing on the transfer of velocity to energy velocity rather than a combination of velocity and mass transfer to energy into the wall. This transferred energy is the initial Work put into the wall. For the force we can take the Kinetic energy and divide it by the distance traveled, in this case the distance traveled in one frame. Through this calculation we can get the distance the parts of the wall will have to travel because of the energy transferred to the wall. The direction of the travel will be the middle ground between the direction of the moving object and the normal vector of the specific part of the moving object. The direction of the moving object comes from the F (force variable), this always has a direction and because it is calculated by dividing the kinetic energy by the distance traveled (in one frame) AND the distance traveled is along the path of this object the distance in which the wall should travel is also impacted by the distance traveled of the moving object. The normal force of the moving object impacts the direction by also applying a force to the part where the moving object hits the wall. The combination of these two vectors or forces will result in the final direction in which the wall-part should travel.

With enough energy stored in the moving object it will break through the wall and with too little the bullet will come to a halt, with possible dents left in the wall. It is also possible for the normal forces of the wall to push the object away or redirect it. With the basics of the physics part of the project explained we can start working on the final product and how it all fits together.

Below are some real life or physics parts that will be ignored because of over complication, time restraints or irrelevancy to the final product
– Air restriction
– (Bullet) Tumbling or yaw
– Gravity
– Object elasticity
– Heat and sound generation during the impact

3. Vertex copying
The first step in creating a deformable wall is to displace the vertices according to the mesh it hits. At first i did this my directly copying the vertices of the wall to the positions of the vertices on the object it hits. This method of deforming the wall did work but it had some limitations. First, if the amount of vertices in the wall was greater than the amount of vertices in the object it hits, some vertices of the wall will overlap with each other because multiple vertices get positioned on 1 specific vertex on the bullet. This then leaves a trail of a lower resolution piece of wall, which is not bad at first but it could create some complications later on regarding the tearing of the wall. The second reason why i did not proceed further with this method is that copying the vertices means that they will follow the moving object no matter where it goes. This could cause the wall-vertices to move away from the wall in the opposite direction if the moving object bounces back after hitting the wall, this should not happen.

4. Vertex pushing
The next thing i added was a change to the way the wall deformed, because of the weird deformation which was deforming outwards. I changed this by creating a force at each of the vertices on the bullet which look for the closest vertex on the wall and push this vertex away. By doing this the wall cannot face outwards when the bullet bounces back away from the wall. In addition to this the bullet also cannot decrease the resolution on the wall by placing certain vertices on top of each other. On problem this method of deformation still has is that the wall vertices which clip into the bullet get pushed away to the other side (towards the inside of the bullet). To counter this problem i changed the push direction to the normal of the vertex, this almost completely fixes the problem mentioned above but it is not 100% perfect. If the vertex on the wall does not have a closest vertex which is facing in the right direction to push (eg. the closest vertex is a vertex on the back of the bullet), the wall-vertex still gets pushed into the wrong direction. This problem can be solved as well but for the time being i left it as is because it only occurs when the bullet is at higher speeds. This speed in unity can be adjusted to get the correct simulation results (for example the input is 100m/s but the unity-speed is that speed divided by 10)

The initial force adding function for the wall vertices

5. Forces on the bullet
Now that the object is able to push the vertices in the wall it is time to slow the bullet down to only let the object make dents in the wall. With the physics explanation done previously we know a few forces can slow down the object. The most prominent and the one we will use in this research is the normal force of the wall to the object with the reduction of energy in the thrown object caused by this event. The first prototype of this physics-handler i made was not very accurate to real physics. I started by giving it the direction towards the object as the normal (-transform.forward) and dividing that by 0.05 (for testing purposes). In addition to that the transform.forward does not change with the deformation, so the deformed wall parts cannot redirect the object, there is only a force along the general direction of the wall-face. I also added a stop condition in this part in case of the bullet moving at a very slow speed which causes the simulation to calculate for a very long time without any change.

The initial physics function (redirection of the object based on the forward position of the wall)

This did contain the base thoughts and way on how i wanted to construct the physics in the scene. One of the big changes that had to be made is the correction of the forward transform to the actual normal vectors of the wall onto the object. The new normal vector can be calculated by adding all the normals of the mesh and normalizing it to get a magnifiable vector which is in the correct direction. The new function is shown below.

Improved physics function (calculates general normal vector on all the touched wall parts’ normal vector)

In the function above it can also be seen that the way of adding the force is also changed, the function now uses the AddForce function from the Unity rigidbody. This way the force can be added more accurately with little effort because of the use of a built-in function.

Now might also be a good time to explain the different unity force modes, which i changed in the new physics function. Standard the forcemode is Acceleration, this DOES NOT use the objects mass and adds a continuous force to this object, sort of like riding a bike, you constantly add force to the pedals which propels the object forward. The next mode is Force this DOES us the object’s mass and adds the same continuous force to the object, force mode feels slower than acceleration because it takes in count the mass of the object you are trying to push. The next mode is Velocity change this mode is the fastest way of adding a force, it DOES NOT use the object’s mass and sets the velocity to the inputted value. The last mode, and the one that is used in the new physics function is Impulse mode, adds all the force to the object in an instant but it DOES use the object’s velocity. This way of adding force can be similar to kicking a ball, all the force is applied to the ball at once

For the improved physics function the choice was made to use the Impulse mode to add force onto the thrown object but later on in the development it seemed more logical to put the mode as Force. As mention earlier the Impulse mode is like kicking a ball. With the impulse mode active in the original function each frame the same method of adding a force is used, which implies that each frame the thrown object is “kicked back” by the wall. The Force mode is more like a flow of continuous force added like air resistance for example. In this case the wall could be seen more as a continuous force rather than a constant object actively trying to push the thrown object in the other direction. So in an updated physics function the force mode is updated to Force instead of Impulse.

The final physics handler function, this function mainly handles the normal force onto the thrown object and the deceleration of said object.

In the picture above there can also be seen that there are two ways of adding the force, the first method is according to the real physics model and the second method is by using a more visually active function. The non-realistic method is kept in the simulation for users to better observe the changes and deformations of the simulation. The realistic function does not have a lot of visual changes because the variables cannot exceed a certain value in order to let the simulation run smoothly (speeds higher than 100-200 allow the thrown object to move through the wall without deforming it).

In the final physics function the correct way of adding the normal force is also used. As explained earlier the normal force is different when you take angles into account.

6. Bullet shapes
Until now the object which hits the wall could only be a sphere or cylindrical shape. This is because the calculation can only be done by having a central impact point and a radius in which impact vertices are gathered. This should be changed to house a wider variety of shapes as objects thrown at the wall. The current deformation system worked, as said earlier, only with spherical or cylindrical shapes. This is because at the collision start the simulation only looks for the transform of the thrown object and looks in a certain radius around this point. All the vertices within this radius on the wall will deform which causes the impact hole to be circular. Luckily this method can easily be changed to have the impact hole shape like the contour of the thrown object. Instead of looking at 1 point and calculating all the vertices from that point it is possible to look from multiple points on the wall and add all the vertices in a smaller range around these points. The points where the simulation must look can be the vertices on the bullet, which are the points of impact. By doing this you run the original code for calculating which vertices should move, multiple times but on a smaller scale. Doing so creates a system which can accumulate all possible shapes as thrown objects. The only downside is that the ‘impact face’ of the object should have enough vertices to create the desired shape in the wall.

GetImpactVertices function for gathering the vertices on the wall to deform in the simulation. The impactPoint array is an array of all the front facing vertices of the thrown object (points that could cause a deformation on the wall), radius is usually set around 0.05.
Function to get the frontal vertices of the thrown object, this is done by looking which vertex normal has a smaller angle than 90 degrees between the normal in question and the transform.forward vector.
A dent roughly shaped like the blender monkey, it might be hard to see and/or inaccurate because of the low resolution wall

7. Wall Tearing
This subject was next on the list, to create holes where the thrown object would’ve pierced the wall or made holes. Implementing this function seemed rather easy because the only thing i had to do was removing certain triangles from the mesh but there were some things i had to adjust to make this method work. The wall tearing i had in mind worked by checking the distance between two vertices and if this distance was greater than a specified number the corresponding triangle(s) should be removed. First to be constructed was the for loop which checks the vertex distances. This distance should only be checked between a vertex and its neighbors.

Sketch used to determine which vertices had to be checked in order to get the right distance checking for wall tearing. The wall is based on this mesh pattern, res is the resolution so a row (and column) of vertices.

Because the wall is made up of the pattern shown above it is also known how the triangles are made and we know which vertex connection constructs which triangle. Based on this information we can look through the entire triangle list and check for each triangle group of 3 if the length between a vertex, for example vertex -1 and the base vertex (the red one in the picture) is greater than the maximum distance. This distance can be calculated by inserting the IDs given in the triangle array into the vertices array which outputs the correct vertices to calculate the distance between. When this distance is greater than the given number the first logical step would be to remove the vertex in question and the 3 associated with it from the triangle array. Doing this will cause the mesh to remove random triangles and tear the entire mesh apart, which is not the desired result. Instead the correct way of ‘removing’ triangles is to set all the IDs in question to 0, this way the size of the array stays the same and only the correct faces will be removed from the wall mesh when the need is there.

The function which handles mesh tearing the the wall

During the process of implementing this feature it is also important to determine the correct timing of activating this function. First i only thought calling it at the end would suffice but this could cause inaccuracies later on. By only calling the function at the end of the simulation allows the thrown object to be applicable to forces by the wall for a longer period of time. This is the case because destroyed faces also remove their respective vertices, this is done by the Optimize function called at the end of function seed above. When a face should be destroyed but the simulation still lets it be there it applies a force to the thrown object when in contact with it. This can cause inaccuracies in the outcome of the simulation. By removing the vertices and faces during the simulation the vertices which should be destroyed will be detached from the wall and no longer count as a part of the wall and thus no longer have stable force on the thrown object. By removing these detached vertices the outcome will be more realistic.

Hole created by the thrown object, take not that a square hole is created due to the limited resolution of the wall (wall resolution of 8)
A more realistic hole with a higher wall resolution, the square shape can still be visible but it is a lot less noticabe (wall resolution of 32)

8. Accurate physics implementation and adjusting
With this all working it was time to evaluate some of the work that was done and adjust or implement the physics where necessary. The main part which could use improvement is the vertex pushing, this works in the context the simulation but it is not yet very realistic and it does not use or is based on real physics functions. Earlier on in this blog the physics behind the simulation is explained, this is the time to implement most of this information into the code, the vertex pushing function to be exact. The vertex pushing function still needs the correct travel distance when pushed by the thrown object. This can be added by using the functions mentioned in the physics explanation earlier in this post. By calculating the difference in energy when the object hits the wall caused by the counter forces of the wall, we can calculate the correct distance the wall vertices should travel using the Work function (W = F * d).

Improved vertex pushing function including the newly added physics function. The point variable is the vertex on the wall, normal is the corresponding normal, and the third parameter is a force reduction. This parameter is one of the few parts of the simulation which is mostly for non-realistic purposes, it can be seen as a material strength variable and is usually around 0.05.

This newly made function is however not the final form. Like in the function of the adding of the normal force to the thrown object, the correct normal vector at an angle should be different than the one calculated in the picture above. So this needs to change, below can be seen that this angle force is calculated and added to the final force vector. This also causes the extra variable to disappear because the force now is a lot smaller. Without the extra variable the function below is also a lot more realistic.

The final function for adding force to wall vertices, the forcePerFrameDevider now is gone and accurate normal vector adding has been implemented

9. Bullet deformation
In the picture above there can also be seen that there is a function for the thrown object deformation, this is there because it gets the normal from the wall and applies the normal force to the object which causes a deformation on this object’s mesh. Note that the corrected normal calculated in the picture above automatically means that the correct normal force will be applied to the deformation of the thrown object. This function applies the same force the thrown object puts on the wall, on the thrown object, as said earlier in the physics explanation.

The two functions which handle the deformation on the thrown object. The deformation power on this object is not handled according to physics laws because of time constraints

In the picture above the thrown object’s deformation system can be seen, it deforms the object according to an exponential function (picture below). In this function determines how much the thrown object gets deformed based on the distance between the impact vertex and the rest of the object.

function to calculate the deformation on the thrown object, currently it is 1 * e^(-20x). The 1 is the softness of the material, a higher number is a softer material. The 20 is a variable which handles the range in which the object gets deformed, with a lower number the impact travels deeper into the object and also pushes the vertices on the back of the object. With a higher number like 20 only the frontal vertices get pushed away.
A deformed object when hitting a wall with a resolution of 16. Thrown object variables: speed 100, mass 100, structural deformation rate = 1.
A deformed object when hitting a wall with a resolution of 16. Thrown object variables: speed 100, mass 100, structural deformation rate = 10.

10. The prototype
All these changes and additions together make the final prototype, this consists of a object which can adjusted in speed, mass, material softness/strength and shape, this object can be launched at a wall. This wall can be angled, changed in resolution, tearing distance, vertex spreading, and the material strength/softness.

The thrown object is able to leave a mark on the wall representing its shape, this shape will be the same as the object as long as the thrown object has enough vertices. The thrown object itself can also deform, other than the previously mentioned deformation is this process not according to real physics. The deformation of the wall is based on the thrown object applying a force to all the vertices it hits. This force comes from the mass and the velocity from the thrown object, which also accounts for the objects energy. This energy can be transformed into work, which is the force applied over a specified distance, and the vertices in the wall will be pushed back by this force. At the same time the wall exerts a force on the thrown object, which is the same as the force put into the wall by the thrown object. This force is the normal force, which also slows the object down.

The interface of the simulation, variables on the left are the current statistics and on the right are the starting variables, most top 3 are for the wall and the bottom 4 are for the thrown object
The result of the simulation on the previous picture, it did not fully pierce the wall and got bounced back a bit

With the prototype it is possible to test certain shapes of objects with specific speeds and masses to throw at the wall. The wall itself is only able to have a single shape, a square, but in test have shown that it is possible to use other pre-made objects as the wall in the simulation but this does not work consistently.

11. Inaccuracies
Within the simulation there are also some inaccuracies, some greater than others. The first and most notable inaccuracy is the fact that the force exerted on the bullet is not based on real physics. As said earlier, this force is a simple force based on variables given by the user. For this to be realistic there has to be a function which should calculate the exact amount of mass “used” to push the wall back or make a deformation. Right now, when the object hits the wall all of the force applied to the wall comes from the velocity, in reality some of the force from the object also causes the thrown object itself to deform. The percentage of force that has to deform the object itself has yet to be constructed.

Another inaccuracy is dependency on vertices, as said earlier and as seen in some of the pictures, the resolution of the wall matters in some cases. For example, when the wall has a resolution of 8, there will be large spots on the wall where there are no vertices, smaller parts of the Thrown object will pierce the wall without experiencing any resistance or deformation, because there is no wall vertex to apply these functions. This problem is hard to fix with the current system and calls for a overhaul of the collision point detection. Either vertices have to be inserted into the wall on runtime or the wall should also see whether vertices of the thrown object have passed it without applying any force to that part.

The next inaccuracy has essentially been fixed but there is an option to turn it off within the simulation. The normal force exerted on the thrown object can be set to a non-realistic version, this is done to give users more visual change within the simulation, the real force created by the wall on the thrown object is much higher than its non-realistic counterpart, which causes the thrown object to bounce off of the wall almost every time. The non-realistic version of the normal force calculation uses pre-determined variables which gives the simulation a more variable outcome, and as said earlier, it can be set to the real physics when needed.

12. Conclusion
Comparing this simulation to a simulation which was the inspiration for this research, it does lack behind on some parts, the physics could use improvement. Examples of physics improvement would be the thing mentioned in the inaccuracies part, correct deformation on the thrown object and fixing the vertex dependency problem. If possible it would also be nice to have a better view of what happens frame by frame. Other than that the simulation can be accurate in which shape and values are put into it. Advanced shapes can work correctly with the simulation if there are enough vertices. There are also some variables to tinker with to simulate a variety of thrown objects and walls. So inconclusion, the simulation as is could use some improvements, mainly on the physics parts, but the base functionality and realism is definitely there.

13. Pictures

A cone shaped object successfully moving through a standard sphere, without deformation in the thrown object
Object deformation with a Structural deformation rate of 15, a mass of 10 and a speed of 100 (a soft material) targeted at an angled slope
Object deformation with a Structural deformation rate of 5, a mass of 50 and a speed of 100, targeted at an angled slope. The green wireframe is the original shape of the object
Object ricocheting of an left and downward angled wall with deformation. Structural deformation rate of 5, mass of 50 and a speed of 100. The green wireframe is the original shape of the object.
Object deforming with a high vertex count, mass is 20, speed is 100, deformation rate is 40, a very soft material. Also not the ‘spikes’ which form at the front of the object, these are caused by a low vertex count in the wall, which in this case did not apply the force to the entire front of the object.
The dent made in the wall (above) and the deformation on the thrown object (below). the wall a resolution of 16, a max triangle size/tearing distance of 30% maximum increase and a vertex spread factor of 1. The object had the model of a bullet, a speed of 100, a mass of 50 and a softness of 1. The simulation was run with the non-realistic normal vector forces.
The same simulation as the last one but now it ran with realistic normal force physics active, notice that the dent in the wall is a bit more shallow.

14. Sources
Edward C. Klatt MD (2023) The University of Utah Eccles Health Sciences Library, The Internet Pathology Laboratory for Medical Education: Firearms tutorial. Received from: https://webpath.med.utah.edu/TUTORIAL/GUNS/GUNBLST.html

S-cool Limited (2021) S-cool Limited, Energy in deformations. Received from: https://s-cool.co.uk/a-level/physics/deformation-of-solids/revise-it/energy-in-deformations

Banas, T. (2020) Sciencing, How to Calculate Force of Impact. Received from: https://sciencing.com/calculate-force-impact-7617983.html

Unity Technologies (2023) Unity Documentation, Forcemode. Received from: https://docs.unity3d.com/ScriptReference/ForceMode.html

Desmos (2023) Graphical Calculator. Receive from: https://www.desmos.com/calculator?lang=nl