I am trying to create a simple chain between two fixed endpoints. The problem is that I can't seem to get the chain to reach a stable state. Further, the chain is always biased toward one of the endpoints.
Here are my constants and variables:
const NUMBER_OF_LINKS = 100
const CHAIN_LENGTH = 400
const DIST_BETWEEN_LINKS = CHAIN_LENGTH / NUMBER_OF_LINKS
const ITERATIONS = 20 # number of times we iterate through constraints each frame
const GRAVITY = Vector2(0, 300)
var anchor1
var anchor2
var prev_link_positions = []
var links = []
Here's what I do on initialization:
create_links(NUMBER_OF_LINKS)
var first_link = links[0]
var last_link = links[NUMBER_OF_LINKS - 1]
first_link.global_position = anchor1.global_position
last_link.global_position = anchor2.global_position
And here are the adjustments I do each frame:
links[0].global_position = anchor1.global_position
links[NUMBER_OF_LINKS - 1].global_position = anchor2.global_position
for i in range(NUMBER_OF_LINKS):
var acceleration = GRAVITY
acceleration *= delta * delta
var prev_position = links[i].global_position
if not i in [0, NUMBER_OF_LINKS - 1]:
links[i].global_position = 2*links[i].global_position - prev_link_positions[i] + acceleration
prev_link_positions[i] = prev_position
for iteration in range (ITERATIONS):
for i in range(NUMBER_OF_LINKS):
var link = links[i]
var prev_link_position
if i == 0 or i == NUMBER_OF_LINKS - 1:
prev_link_position = links[i].global_position
else:
prev_link_position = links[i-1].global_position
var next_link_position
if i == 0 or i == NUMBER_OF_LINKS - 1:
next_link_position = links[i].global_position
else:
next_link_position = links[i+1].global_position
# get vector to previous link and adjust position
var vec_to_prev_link = prev_link_position - link.global_position
link.global_position += vec_to_prev_link.normalized() * max(vec_to_prev_link.length() - DIST_BETWEEN_LINKS, 0) / 2.0
# get vector to next link and adjust position
var vec_to_next_link = next_link_position - link.global_position
link.global_position += vec_to_next_link.normalized() * max(vec_to_next_link.length() - DIST_BETWEEN_LINKS, 0) / 2.0
When I run this, I almost get what I want, except the chain contorts and never reaches a stable state. Also, it is biased in the first direction I look at when solving the constraints.
It looks something like this:
What am I doing wrong? How can I get a chain that stabilizes with links more uniformly distributed?