Type | Personal project. |
Engine | The Game Engine – The Game Assembly's in house C++ engine. |
Timeframe | 1 week, April 2024 |
Intent | Learning more about game physics by implementing rope simulation from scratch. |
This is a personal project that I ended up adding to the 4th game project at The Game Assembly.
Here's a quick summary of how it works.
The Simulation
The simulation uses nodes and springs.
The nodes are dynamic physics objects, meaning that they have a mass and are affected by forces added to them.
Springs connect the nodes and apply force to them based on a relationship between the spring's natural- and current length.
Showcasing the functionality of changing spring length and adding/removing nodes in run time
// Looping over the nodes, calculating force added by springs
// index1, index2 - Indices of the nodes connected to the spring
spring.vector = myNodes[index1].position - myNodes[index2].position;
spring.direction = spring.vector.GetNormalized();
float tooLongBy = spring.vector.Length() - MAX_LENGTH;
if (tooLongBy > 0.f)
{
myNodes[index1].posistion -= spring.direction * tooLongBy;
spring.vector = myNodes[index1].position - myNodes[index2].position;
}
float spring.Length = spring.vector.Length() - SPRING_LENGTH;
Vector3 springForce = SPRING_STIFFNESS * spring.length * spring.direction;
myNodes[index1].AddVelocity(springForce);
myNodes[index2].AddVelocity(-springForce);
The Visualization
The rope is an animated model that I created in Blender.
Based on the simulation data, the pose of the skeletal mesh is updated.
This is how it turned out:
// Looping over the the skeleton of the rope mesh,
// calculating the joint transforms based on the simulation
Vector3 forward = springs[springIndex].dir;
Vector3 up = { 0.f, 1.f, 0.f };
Vector3 right = (up.Cross(forward)).GetNormalized();
up = forward.cross(right);
Quaternion quaternion = CreateFromOrthonormalBasisVectors(right, up, forward);
Matrix4x4 jointRotation = CreateRotation(quaternion);
Matrix4x4 jointPosition = CreateTranslationMatrix(myNodes[nodeIndex].position);
modelPose.JointTransforms[joinIndex] = jointRotation * jointPosition;
Credits & inspiration
Video going over basic rope simulation.
Graphics for game project
Emma BlomStrans
Love Dagerborn
Oliver Sillén Forström
Ishman Zaman