Simulating a hanging chain

Blitz3D Forums/Blitz3D Programming/Simulating a hanging chain

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

The diff is a distance measurement which tells you how far from it's restlength a link is. It uses this to adjust both points proportionate to their inversemass so that a heavier particle isn't moved as far as a lighter one but they still maintain their distance appart.

Really the 'Mass' field should be 'InverseMass'. Note if you set this to 0 the particle is immovable automatically.

I've changed a couple of things. Your initial particle positions were causing major energy in the system so I fixed this. I also made the inversemasses lower so that gravity has a bigger effect. It seems to work ..

Graphics 640, 480, 16, 0
SetBuffer BackBuffer()
SeedRnd MilliSecs()
TFormFilter False
frameTimer = CreateTimer(60)

timeStep# = 0.05 ;0.016666
g# = 9.81
drag# = 0.995
numLinks = 100
massOfEachLink = 1
restLength# = 4
Iterations = 1



Type playerType
Field x#, y#, vX#, vY#, aX#, aY#
Field mass#
End Type

player.playerType = New playerType
player\x = 100
player\y = 250
player\mass = 1


Type clawType
Field x#, y#, aX#, aY#
End Type


Type chainLinkType
Field x#, y#, oldX#, oldY#, aX#, aY#, mass#
End Type

Dim chainArray.chainLinkType(numLinks - 1)
For i = 0 To numLinks - 1

  chainArray(i) = New chainLinkType
  chainArray(i)\x = 120 + i * 4 ;i * 540 / (numLinks - 1)
  chainArray(i)\y = 100
  chainArray(i)\oldX = chainArray(i)\x
  chainArray(i)\oldY = chainArray(i)\y
  chainArray(i)\mass = massOfEachLink

  ;set end points to have infinite mass
  If i = 0 Or i = ( numlinks-1 )
 	  chainArray(i)\mass = 0 
  EndIf	

Next




While Not KeyHit(1)
WaitTimer frameTimer
Cls


  ; Controls



  For i = 0 To numLinks - 1

    ; Apply gravity to particles which don't have an infinite mass
	If chainArray(i)\Mass > 0   chainArray(i)\aY = chainArray(i)\aY + g / chainArray(i)\mass

    ; Verlet Integration
    tempX# = chainArray(i)\x
    tempY# = chainArray(i)\y

    chainArray(i)\x = chainArray(i)\x * (1.0 + drag) - drag * chainArray(i)\oldX + chainArray(i)\aX * timeStep * timeStep
    chainArray(i)\y = chainArray(i)\y * (1.0 + drag) - drag * chainArray(i)\oldY + chainArray(i)\aY * timeStep * timeStep
    chainArray(i)\oldX = tempX
    chainArray(i)\oldY = tempY

    ; Reset acceleration after moving particle
    chainArray(i)\aX = 0 : chainArray(i)\aY = 0
  Next



  ; Make each link experience a force from the surrounding ones
	For j = 1 To Iterations
	  For i = 0 To numLinks - 2
	
	    temp_dx# = chainArray(i + 1)\x - chainArray(i)\x
	    temp_dy# = chainArray(i + 1)\y - chainArray(i)\y
	    temp_Separation# = Sqr(temp_dx * temp_dx + temp_dy * temp_dy)
	    temp_Extension# = temp_Separation - restLength
	
	    ; Start 
	    temp_SpringForce# = temp_Extension / ( temp_Separation * (chainArray(i)\mass + chainArray(i + 1)\mass) )
	    chainArray(i)\x = chainArray(i)\x + chainArray(i)\mass * temp_dx * temp_SpringForce
	    chainArray(i)\y = chainArray(i)\y + chainArray(i)\mass * temp_dy * temp_SpringForce
	    chainArray(i + 1)\x = chainArray(i + 1)\x - chainArray(i + 1)\mass * temp_dx * temp_SpringForce
	    chainArray(i + 1)\y = chainArray(i + 1)\y - chainArray(i + 1)\mass * temp_dy * temp_SpringForce
	
	  Next
	
	 Next

  ; Draw Links
  For i = 0 To numLinks - 1
    Rect chainArray(i)\x, chainArray(i)\y, 1, 1, 1
  Next



Flip
Wend
End


p.s. Use the TAB button to indent your code .. not spaces!!

Stevie