﻿

Blender Springs and Dampers (021; 29.09.2009; blender)

I have decided to extend standard Blender Game Engine with springs and dampers. It is useful when working with mechanisms.

Linear spring.

Create scene with Cube and Plane like this: Set cube as Rigid Body and put game logic: Put in text editor python script ini.py with this content:
```import GameLogic

scene = GameLogic.getCurrentScene()

GameLogic.Object1=scene.objects['OBPlane']
GameLogic.Object2=scene.objects['OBCube']

Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition

GameLogic.IniLength=Loc2-Loc1

GameLogic.Stiff=20
```

and spring.py:
```import GameLogic

Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition

Length=Loc2-Loc1

Force=(Length-GameLogic.IniLength)*GameLogic.Stiff

Force1=[0,0,Force]
Force2=[0,0,-Force]
GameLogic.Object1.applyForce(Force1, False)
GameLogic.Object2.applyForce(Force2, False)
```

How it works?
ini.py script started once at the beginning of simulation:
• put in global variable objects that will be connected with spring,
• put in global variable distance between objects centers - initial spring length,
• put in global variable spring stiffness.
spring.py started every time-step:
• read objects centers locations and calculate distance between them,
• calculate force in spring: spring stiffness * (actual length - initial length),
• create global force vectors and add them to objects.

3D spring.

For complex spring witch working with two rigid body objects create scene witch Cube1, Cube2 and Plane objects. Just for one rigid body object with Bounds/Box collision make logic: ini.py content:
```import GameLogic
scene = GameLogic.getCurrentScene()
GameLogic.Object1=scene.objects['OBCube1']
GameLogic.Object2=scene.objects['OBCube2']
Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition
IniLengthX=Loc2-Loc1
IniLengthY=Loc2-Loc1
IniLengthZ=Loc2-Loc1
GameLogic.IniLength=(IniLengthX**2+IniLengthY**2+IniLengthZ**2)**(0.5)
GameLogic.Stiff=100
```

spring.py content:
```import GameLogic
Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition
LengthX=Loc2-Loc1
LengthY=Loc2-Loc1
LengthZ=Loc2-Loc1
Length=(LengthX**2+LengthY**2+LengthZ**2)**(0.5)
Force=(Length-GameLogic.IniLength)*GameLogic.Stiff
ForceX=Force*LengthX/Length
ForceY=Force*LengthY/Length
ForceZ=Force*LengthZ/Length
Force1=[ForceX,ForceY,ForceZ]
Force2=[-ForceX,-ForceY,-ForceZ]
GameLogic.Object1.applyForce(Force1, False)
GameLogic.Object2.applyForce(Force2, False)
```

There were necessary to calculate distance in 3 dimensions and project spring force to three components vector.

Finished scene: Blender3dSpring.blend.

Spring visualization.

It will be helpful to create spring mesh that represents spring just generated.

You can make spring mesh extruding circle through spiral curve. I propose to use Parametric Object script (http://www.blinken.com/blender-plugins.php).

Parametric representation of spring surface:  For simple visualization you can connect spring with one Ball and one 6DOF constraint on the ends. For dynamic stretching you probably could use armature. I make simple script that scales spring every frame. You will see it later.

Damping in Blender Game Engine.

You should notice how Damp and RotDamp parameters affect objects in Game Engine.

Damp parameter involve only linear movement. Engine add to object damping force opposite to linear velocity. Force is multiplication of velocity, Damp and mass.

PRotDamp parameter involve only rotational movement. Engine add to object damping moment of force opposite to angular velocity. Force is multiplication of angular velocity, RotDamp and rotational inertia. Inertia is probably calculated as multiplication of mass and Form factor.

This parameters involve global objects movement, but they have few abilities in mechanics even though they can be set independently.

3D damper.

It will be very similar to spring creation. Start with Cube1, Cube2 and Plane. Just for one rigid body object with Bounds/Box collision make logic: ini.py content:
```import GameLogic
scene = GameLogic.getCurrentScene()
GameLogic.Object1=scene.objects['OBCube1']
GameLogic.Object2=scene.objects['OBCube2']
GameLogic.Damping=5
```

spring.py content:
```import GameLogic
Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition
V1=GameLogic.Object1.getLinearVelocity(False)
V2=GameLogic.Object2.getLinearVelocity(False)
LengthX=Loc2-Loc1
LengthY=Loc2-Loc1
LengthZ=Loc2-Loc1
Length=(LengthX**2+LengthY**2+LengthZ**2)**(0.5)
Vx=V2-V1
Vy=V2-V1
Vz=V2-V1
V=(Vx*LengthX+Vy*LengthY+Vz*LengthZ)/Length
Force=GameLogic.Damping*V
ForceX=Force*LengthX/Length
ForceY=Force*LengthY/Length
ForceZ=Force*LengthZ/Length
Force1=[ForceX,ForceY,ForceZ]
Force2=[-ForceX,-ForceY,-ForceZ]
GameLogic.Object1.applyForce(Force1, False)
GameLogic.Object2.applyForce(Force2, False)
```

Because for projecting velocity vector we need cosines of this vector angles, we used distances between objects to calculate cosines.

Source file: Blender3dDamper.blend.

Damper visualization.

Just need two cylinders and three constraints. Connect cubes witch cylinders at centers with Ball constraint and connect cylinders together with linear constraint (6DOF constraint with only LinZ degree of freedom).

See file: BlenderDampVisible.blend. Kelvin - Voigt model.

The most useful is parallel connection of spring and damper. Just change scripts like this:

ini.py:
```import GameLogic
scene = GameLogic.getCurrentScene()
GameLogic.Object1=scene.objects['OBCube1']
GameLogic.Object2=scene.objects['OBCube2']
Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition
IniLengthX=Loc2-Loc1
IniLengthY=Loc2-Loc1
IniLengthZ=Loc2-Loc1
GameLogic.IniLength=(IniLengthX**2+IniLengthY**2+IniLengthZ**2)**(0.5)
GameLogic.Stiff=7
GameLogic.Damping=2
```

spring.py:
```import GameLogic
Loc1=GameLogic.Object1.localPosition
Loc2=GameLogic.Object2.localPosition
V1=GameLogic.Object1.getLinearVelocity(False)
V2=GameLogic.Object2.getLinearVelocity(False)
LengthX=Loc2-Loc1
LengthY=Loc2-Loc1
LengthZ=Loc2-Loc1
Length=(LengthX**2+LengthY**2+LengthZ**2)**(0.5)
Vx=V2-V1
Vy=V2-V1
Vz=V2-V1
V=(Vx*LengthX+Vy*LengthY+Vz*LengthZ)/Length
ForceSpring=(Length-GameLogic.IniLength)*GameLogic.Stiff
ForceDamper=GameLogic.Damping*V
ForceX=(ForceSpring+ForceDamper)*LengthX/Length
ForceY=(ForceSpring+ForceDamper)*LengthY/Length
ForceZ=(ForceSpring+ForceDamper)*LengthZ/Length
Force1=[ForceX,ForceY,ForceZ]
Force2=[-ForceX,-ForceY,-ForceZ]
GameLogic.Object1.applyForce(Force1, False)
GameLogic.Object2.applyForce(Force2, False)
```

Surce file: BlenderSpringDamp.blend

See full spring and damper scene with my best visualization: BlenderSpringDampVisible.blend Using of springs and dampers.

Notice, that springs and dampers are connect with 'virtual ball' constraints witch don't limit system kinematic (don't fix degrees of freedom) and just change dynamic behavior. So it is required to use many Rigid Body Joints constraints (see article - in Polish).

Simulation precision.

I made some tests of Bullet Physics implemented in Blender Game Engine. In my opinion, you can't use this simulation with engineering applications because of non perfect precision (and of course we don't now well how bullet calculate inertia, and constraints are not perfectly rigid). But for artistic and drafts GE is perfect with it's realism and performance.

Fist test: Record object free fall with IPO. You can calculate theoretical fall time and compare it with simulation (simple equation h = g*(t^2)/2). Remember about zero damping and default 60 frames per second, witch you can change with script line:

```GameLogic.setLogicTicRate(NumberOfFramesPerSecond)
```

This test confirm good precision of calculate of dynamic object with constant acceleration.

Second test: We can check natural frequency of system with object hanged on spring, calculated with equation: Nonlinear spring.

Typical progressive third order spring have force calculated with script line:
```Force=((Length-GameLogic.IniLength)**(3))*GameLogic.Stiff
```

Afterword.

My concept of springs and dampers is a bit difficult when we want to have several of it. I thought about Python script generating full spring or damper (constraints, logic bricks, scripts), but Blender 2.49 API haven't access to logic...So be patient and careful when copying or renaming objects.

In this case I'm waiting for new Blender 2.5 API.

Maybe I ought to learn C and C++, take part in Blender and improve game engine with simple springs and dampers panel...?

© Copyright Sebastian Korczak 2009 - 2020  