A pattern defines the power of the rumble effect that needs to be applied to the specified motor within the controller. To begin with, open the file specified above (ForceFeedbackEffects.xml) and let's look at the pattern definitions. The sample's field basically sends a power value to the motor ranging from 0 -> 1 (unspecified- maximum rumble).
- <Pattern name="100" samples="1" />
This pattern is called "100" and it uses one constant value "1" over the entire length of the pattern.
Pic1: Full power (samples = 1)
- <Pattern name="square" samples="1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0" />
This pattern is called "square" and it applies full power to the motors for the first 8 samples, and then applies no values to the following 8 samples.
Pic2: Approx Full power, then none (samples = 1,0)
- <Pattern name="50" samples="0.5" />
This pattern is called "50" with a constant 1/2 power.
Pic3: 50% power (samples = 0.5)
- <Pattern name="triangle" samples="0,0.15,0.3,0.45,0.6,0.75,0.9,1,1,0.9,0.75,0.6,0.45,0.3,0.15,0" />
This pattern is called "triangle" and it uses the full 16 values to create an effect.
If you note the name of this effect "triangle", the first 8 samples grows from 0 -> 1 and the last 8 decreases from 1 -> 0. This simulates a triangle pattern by slowly building up the strength of the effect and then goes back down again to zero to create a loop.
Pic4: Approx representation of the triangle wave
This describes the concept of patterns for the power that will be delivered to the controller's motors. The range of the power runs from 0 -> 1 and the maximum variation that you can add to the samples is 16.
Creating your own patterns is as simple as defining a new name for the pattern and then specifying the values that will be played at the motor (with a maximum of 16 individual values). If you decide to use less than the full 16 samples, make sure they are divisible by 2, so the system can distribute the effect evenly over the timeline. For example: 1, 2, 4, 8, 16 samples within the effect.
Envelopes are used as overrides to the patterns. They complement the pattern by either blending in or out the actual effect, depending on how you set the envelope up.
- <Envelope name="linearDecrease" samples="1,0" />
This envelope when used in conjunction with an effect will allow the underlying effect to play at the maximum to begin with, then over time, it reduces the impact that the effect can send to the motor, all the way down to zero.
Let us consider the pattern above called "0.5" as an example.
Pic5: Envelope with a pattern 0.5
Now the representation of the envelope for "linearDecrease" is described below.
Pic6: Linear decrease envelope (note the 1 - 8 max samples)
Now this will be the result when you combine the pattern 0.5 with the envelope linear decrease. The pattern starts off at the maximum value (0.5) since the envelope plays at the maximum possible value specified within the pattern.
Then over the course of the effect, the envelope reduces the ability of the pattern to play at its set value until it reaches zero.
Pic7: Result of pattern 0.5 + linear decrease envelope
The previous example was quite simple and this time we will show a more complex effect in action which is being adjusted by the envelope. The pattern will be a saw-tooth effect, a series of 0,1,0,1.0,1,0,1.0,1,0,1,0,1,0,1's.
Pic8: A saw-tooth pattern
Pic9: Linear decrease envelope (note the 1 - 8 max samples)
Now when we apply the linear decrease envelope on top of the saw-tooth pattern, the resulting effect will be:
Pic10: Saw-tooth with Linear decrease applied
This shows you how to combine an effect to create pattern, and then when applied with the envelope, the effect tries its best to play the full pattern but it gets restricted by the envelope.
The combination of a pattern and envelope saves you time in having to calculate the actual true values of the decrease in power. Which would resemble values such as 0, 0.95, 0, 8.2, 0, etc., when represented as a comma separated string within the *.xml file.
The effects section will be the actual part that will be called using code, Flowgraph or any other means to trigger the effect to play. The effect encapsulates the pattern and envelope together, and then also assigns it to the specific motor that you want to play it on. We will again run through a few examples of different variations of the effects, and how to set them up below.
To begin with, let's breakdown this block to understand the basic flow.
- <Effect name="explosion" time="1.0" >
- Effect name = Name of the effect that will be referenced in the FlowGraph or code. So the name the effect based on its function in a logical manner.
- Time = Specifies the time length for which the rumble effect will be played.
- <MotorAB frequency="1" pattern="100" envelope="linearDecrease" />
- MotorAB = The motor you want to target this effect on. You can either target MotorA or MotorB individually, or both together at once with MotorAB (as in this example). We give you the option to split them up as you may want to play the same effect on both motors, but with a different envelope!
- Frequency = Leave this at one (There is no real need to change this). Increasing this number will start to blend all the values together, remember that the motor has to power-up to the level that you set, and we have found that the frequency of 1 is optimal to "feel" all the data that you are sending to the motors. When increasing this value (to use the phrase = “can’t see the wood for the trees”), there will be too many values that are being sent to the motors which you won’t be able to distinguish the difference between them. Try increasing/decreasing the time instead of frequency to modify the played effect.
- Pattern = Specifies the pattern that you want to play inside this effect.
- Envelope = Specifies the second value that will be added to your effect (for example, linearDecrease).
This effect will send same pattern to both the motors, with the same envelope.
This effect is similar to the above effect, but we are splitting the Motors (A,B) into their own line for individual control (Even though they are same).
MotorA is running at max power (but clamped to 50% output due to the envelope)
MotorB is running at 0.12 power, and moves towards to zero at the end due to the LinearDecrease envelope.
Bad combinations of Patterns and Envelopes
In certain circumstances, if you're not paying close attention, you can end up cancelling out the FFB effect that you want to play. This can happen when the envelope is working in the opposite direction to the pattern. Let's look at the below example:
Based on the above example, the Square pattern (1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0) plays at the start of the effect (1) and does not play anything towards the end of the effect (0). The Gausscharge envelope (0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1) is the exact opposite and just cancels out the pattern.
We have made some console variables to allow you to investigate the ForceFeedback system. This tool allows you to visualize the inputs that are being sent to the motors.
|Turns on/off ForceFeedback system debug.|
|Play a ForceFeedback effect, passed by name as first parameter. For example, ffs_PlayEffect explosion.|
|Reload ForceFeedback system data.|
|Stop all the active ForceFeedback effects.|
Pic11: Debug visual output from the ffs_debug CVar
The ForceFeedback system is provided with dedicated Flow Graph nodes. These allow access to designers and artists to configure test, and control the effects easier.
Pic12: FlowGraph nodes for the ForceFeedback system.