#Region Includes
#include <GUIConstantsEx.au3>
#include <GDIPlus.au3>
#EndRegion


#Region Declarations
;~ Window
Global $wWidth = 800
Global $wHeight = 600
Global $wMiddle_x = $wWidth / 2
Global $wMiddle_y = $wHeight / 2
Global $middle_x = @DesktopWidth/2
Global $middle_y = @DesktopHeight/2

;~ Env
Global $pi = 3.141592653589793
Global $g = 1
Global $f = 0.999
Global $x[3], $y[3], $th[3], $v[3], $a[3], $l[3], $m[3]

;~ INIT pendulum 1
$l[1] = 200
$m[1] = 20
$th[1] = 0.4*$pi
$v[1] = 0.0
$a[1] = 0
$x[1] = $wMiddle_x + $l[1] * sin($th[1])
$y[1] = 0.5*$wMiddle_y - $l[1] * cos($th[1])

;~ INIT pendulum 2
$l[2] = 200
$m[2] = 20
$th[2] = 0.5*$pi
$v[2] = 0.0
$a[2] = 0
$x[2] = $x[1] + $l[2]*sin((($th[2]-180)*$pi)/180)
$y[2] = $y[1] - $l[2]*cos((($th[2]-180)*$pi)/180)
#EndRegion


#Region Gui
$hGui = GUICreate("Form1", $wWidth, $wHeight, $middle_x-($wWidth/2), $middle_y-($wHeight/2),-2147483648)
GUISetState(@SW_SHOW)
#EndRegion


#Region ### START GDI+ ###
_GDIPlus_Startup()
$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)

;~ Bitmaps
$hGraphicBitmap = _GDIPlus_BitmapCreateFromGraphics($wWidth, $wHeight, $hGraphic)
$hHistoryBitmap = _GDIPlus_BitmapCreateFromScan0($wWidth, $wHeight)
$hLegBitmap = _GDIPlus_BitmapCreateFromScan0($wWidth, $wHeight)

;~ Buffers
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hGraphicBitmap)
$hHistoryBuffer = _GDIPlus_ImageGetGraphicsContext($hHistoryBitmap)
$hLegBuffer = _GDIPlus_ImageGetGraphicsContext($hLegBitmap)

;~ Smoothing
_GDIPlus_GraphicsSetSmoothingMode($hBuffer, 4)
_GDIPlus_GraphicsSetSmoothingMode($hHistoryBuffer, 4)
_GDIPlus_GraphicsSetSmoothingMode($hLegBuffer, 4)

;~ First Clearing
_GDIPlus_GraphicsClear($hBuffer, 0xFFFFFFFF)
_GDIPlus_GraphicsClear($hHistoryBuffer, 0xFFFFFFFF)
_GDIPlus_GraphicsClear($hLegBuffer, 0xFFFFFFFF)

;~ Pens
$hPen = _GDIPlus_PenCreate(0xFF0000FF, 1)
#EndRegion ### END GDI+ ###


#Region EventMode
Opt("GUIOnEventMode", 1)
GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
#EndRegion


#Region Loop
While 1
   _Calc()
   _Draw()
WEnd
#EndRegion


#Region Functions
Func _Calc()
;~    Acceleration 1
   $num1 = -$g * (2*$m[1]+$m[2]) * sin($th[1])
   $num2 = -$m[2] * $g * sin($th[1]-2*$th[2])
   $num3 = -2 * sin($th[1]-$th[2]) * $m[2]
   $num4 = $v[2]*$v[2] * $l[2] + $v[1]*$v[1] * $l[1] * cos($th[1]-$th[2])
   $den = $l[1] * (2 * $m[1] + $m[2] - $m[2] * cos(2*$th[1]-2*$th[2]))
   $a[1] = ($num1 + $num2 + ($num3 * $num4)) / $den

;~    Acceleration 2
   $num1 = 2 * sin($th[1]-$th[2])
   $num2 = ($v[1]*$v[1] * $l[1] * ($m[1]+$m[2]))
   $num3 = $g * ($m[1]+$m[2]) * cos($th[1])
   $num4 = $v[2]*$v[2] * $l[2] * $m[2] * cos($th[1]-$th[2])
   $den = $l[2] * (2 * $m[1] + $m[2] - $m[2] * cos(2*$th[1]-2*$th[2]))
   $a[2] = ($num1 * ($num2 + $num3 + $num4)) / $den

;~    Angles
   $v[1] += $a[1]
   $v[2] += $a[2]
   $v[1] *= $f
   $v[2] *= $f
   $th[1] += $v[1]
   $th[2] += $v[2]

;~    EndPoints
   $x[1] = $wMiddle_x - $l[1] * sin($th[1])
   $y[1] = 0.5*$wMiddle_y + $l[1] * cos($th[1])
   $x[2] = $x[1] - $l[2]*sin($th[2])
   $y[2] = $y[1] + $l[2]*cos($th[2])
EndFunc


Func _Draw()
;~    Clear
   _GDIPlus_GraphicsDrawImageRect($hLegBuffer, $hHistoryBitmap, 0, 0, $wWidth, $wHeight)

;~    Draw pieces
   _GDIPlus_GraphicsDrawLine($hLegBuffer, $wMiddle_x, 0.5*$wMiddle_y, $x[1], $y[1], $hPen)
   _GDIPlus_GraphicsFillEllipse($hLegBuffer, $x[1]-($m[1]/2), $y[1]-($m[1]/2), $m[1], $m[1])
   _GDIPlus_GraphicsDrawLine($hLegBuffer, $x[1], $y[1], $x[2], $y[2], $hPen)
   _GDIPlus_GraphicsFillEllipse($hLegBuffer, $x[2]-($m[2]/2), $y[2]-($m[2]/2), $m[2], $m[2])

;~    History
   _GDIPlus_GraphicsFillEllipse($hHistoryBuffer, $x[2], $y[2], 2, 2)

;~    Draw finally
   _GDIPlus_GraphicsDrawImageRect($hBuffer, $hHistoryBitmap,0, 0, $wWidth, $wHeight)
   _GDIPlus_GraphicsDrawImageRect($hBuffer, $hLegBitmap,0, 0, $wWidth, $wHeight)
   _GDIPlus_GraphicsDrawImageRect($hGraphic, $hGraphicBitmap, 0, 0, $wWidth, $wHeight)
EndFunc


Func _Exit()
   _GDIPlus_GraphicsDispose($hGraphic)
   _GDIPlus_PenDispose($hPen)
   _GDIPlus_Shutdown()
   Exit
EndFunc
#EndRegion


#Region Event Functions
Func SpecialEvents()
   Select
      Case @GUI_CtrlId = $GUI_EVENT_CLOSE
         GUIDelete()
         _Exit()
   EndSelect
EndFunc
#EndRegion