' Display
' Meta
' Data
' Statics
ShapeCount = 0
' Dynamics
CollisionCount = 0
Gravity.x = 0
Gravity.y = -5
' Create objects.
ShapeCount = ShapeCount + 1
Shape(ShapeCount).CtrRot.x = -220
Shape(ShapeCount).CtrRot.y = 0
i = 0
i = i + 1
r
= 40 + 25 * COS(1.5 * j
) ^ 2 PointChain
(ShapeCount
, i
).x
= Shape
(ShapeCount
).CtrRot.x
+ r
* COS(j
) PointChain
(ShapeCount
, i
).y
= Shape
(ShapeCount
).CtrRot.y
+ r
* SIN(j
)Shape(ShapeCount).Elements = i
Shape(ShapeCount).Mass = i
Shape(ShapeCount).Velocity.x = 0
Shape(ShapeCount).Velocity.y = 0
Shape(ShapeCount).Omega = 0
Shape
(ShapeCount
).Shade
= _RGB(0, 255, 255)CALL CalculateCtrMass
(ShapeCount
) CALL CalculateDiameter
(ShapeCount
) CALL CalculateMOI
(ShapeCount
)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170
'Shape(ShapeCount).CtrRot.y = 0
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170 + 54
'Shape(ShapeCount).CtrRot.y = -31.25
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170 + 54
'Shape(ShapeCount).CtrRot.y = 31.25
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170 + 54 + 54
'Shape(ShapeCount).CtrRot.y = 0
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170 + 54 + 54
'Shape(ShapeCount).CtrRot.y = -31.25 * 2
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 170 + 54 + 54
'Shape(ShapeCount).CtrRot.y = 31.25 * 2
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 28
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 0
'Shape(ShapeCount).Velocity.y = 0
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'''
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = -200
'Shape(ShapeCount).CtrRot.y = 0
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 40 + 25 * COS(j) ^ 2
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 2 * (RND - .5)
'Shape(ShapeCount).Velocity.y = 2 * (RND - .5)
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(0, 255, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 0
'Shape(ShapeCount).CtrRot.y = 0
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 40 + 25 * COS(1.5 * j) ^ 2
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 2 * (RND - .5)
'Shape(ShapeCount).Velocity.y = 2 * (RND - .5)
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(255, 0, 255)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'ShapeCount = ShapeCount + 1
'Shape(ShapeCount).CtrRot.x = 200
'Shape(ShapeCount).CtrRot.y = 0
'i = 0
'FOR j = 0 TO 2 * 4 * ATN(1) STEP .05
' i = i + 1
' r = 50
' PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x + r * COS(j)
' PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y + r * SIN(j)
'NEXT
'Shape(ShapeCount).Elements = i
'Shape(ShapeCount).Mass = i
'Shape(ShapeCount).Velocity.x = 2 * (RND - .5)
'Shape(ShapeCount).Velocity.y = 2 * (RND - .5)
'Shape(ShapeCount).Omega = 0
'Shape(ShapeCount).Shade = _RGB(255, 255, 0)
'CALL CalculateCtrMass(ShapeCount)
'CALL CalculateDiameter(ShapeCount)
'CALL CalculateMOI(ShapeCount)
'w = _WIDTH / 2
'h = _HEIGHT / 2
'b = 20
'FOR n = -1 TO 1 STEP 2
' FOR k = (-w + 2 * 5) TO (w - 2 * 5) STEP b
' ShapeCount = ShapeCount + 1
' Shape(ShapeCount).CtrRot.x = x
' Shape(ShapeCount).CtrRot.y = n * h - n * 5
' i = 0
' FOR j = (Shape(ShapeCount).CtrRot.x - b / 2) TO (Shape(ShapeCount).CtrRot.x + b / 2) STEP 5
' i = i + 1
' PointChain(ShapeCount, i).x = j
' PointChain(ShapeCount, i).y = n * h - n * 5
' NEXT
' Shape(ShapeCount).Elements = i
' Shape(ShapeCount).Mass = 999 ^ 999
' Shape(ShapeCount).Velocity.x = 0
' Shape(ShapeCount).Velocity.y = 0
' Shape(ShapeCount).Omega = 0
' Shape(ShapeCount).Shade = _RGB(255, 255, 0)
' CALL CalculateCtrMass(ShapeCount)
' CALL CalculateDiameter(ShapeCount)
' CALL CalculateMOI(ShapeCount)
' NEXT
' 'ShapeCount = ShapeCount + 1
' 'Shape(ShapeCount).CtrRot.x = n * w - n * 5
' 'Shape(ShapeCount).CtrRot.y = 0
' 'i = 0
' 'FOR j = (-h + 2 * 5) TO (h - 2 * 5) STEP 3
' ' i = i + 1
' ' PointChain(ShapeCount, i).x = n * w - n * 5
' ' PointChain(ShapeCount, i).y = j
' 'NEXT
' 'Shape(ShapeCount).Elements = i
' 'Shape(ShapeCount).Mass = 999 ^ 999
' 'Shape(ShapeCount).Velocity.x = 0
' 'Shape(ShapeCount).Velocity.y = 0
' 'Shape(ShapeCount).Omega = 0
' 'Shape(ShapeCount).Shade = _RGB(255, 255, 0)
' 'CALL CalculateCtrMass(ShapeCount)
' ''CALL CalculateDiameter(ShapeCount)
' 'Shape(ShapeCount).Diameter = 5
' 'CALL CalculateMOI(ShapeCount)
'NEXT
' Walls
b = 10
ShapeCount = ShapeCount + 1
Shape(ShapeCount).CtrRot.x = k
Shape
(ShapeCount
).CtrRot.y
= n
* (_HEIGHT / 2 - b
/ 2) i = 0
FOR j
= (Shape
(ShapeCount
).CtrRot.x
- b
/ 2) TO (Shape
(ShapeCount
).CtrRot.x
+ b
/ 2) STEP 3 i = i + 1
PointChain(ShapeCount, i).x = j
PointChain(ShapeCount, i).y = Shape(ShapeCount).CtrRot.y
Shape(ShapeCount).Elements = i
Shape(ShapeCount).Mass = 999 ^ 999
Shape(ShapeCount).Velocity.x = 0
Shape(ShapeCount).Velocity.y = 0
Shape(ShapeCount).Omega = 0
Shape
(ShapeCount
).Shade
= _RGB(100, 100, 100) CALL CalculateCtrMass
(ShapeCount
) CALL CalculateDiameter
(ShapeCount
) CALL CalculateMOI
(ShapeCount
) Shape(ShapeCount).MOI = 999 ^ 999
ShapeCount = ShapeCount + 1
Shape
(ShapeCount
).CtrRot.x
= n
* (_WIDTH / 2 - b
/ 2) Shape(ShapeCount).CtrRot.y = k
i = 0
FOR j
= (Shape
(ShapeCount
).CtrRot.y
- b
/ 2) TO (Shape
(ShapeCount
).CtrRot.y
+ b
/ 2) STEP 3 i = i + 1
PointChain(ShapeCount, i).x = Shape(ShapeCount).CtrRot.x
PointChain(ShapeCount, i).y = j
Shape(ShapeCount).Elements = i
Shape(ShapeCount).Mass = 999 ^ 999
Shape(ShapeCount).Velocity.x = 0
Shape(ShapeCount).Velocity.y = 0
Shape(ShapeCount).Omega = 0
Shape
(ShapeCount
).Shade
= _RGB(100, 100, 100) CALL CalculateCtrMass
(ShapeCount
) CALL CalculateDiameter
(ShapeCount
) CALL CalculateMOI
(ShapeCount
) Shape(ShapeCount).MOI = 999 ^ 999
LOCATE 1, 1:
PRINT "Click & Drag counter-clockwise to create a shape."
' Proximity detection
ProximalPairsCount = 0
Shape1 = 0
Shape2 = 0
FOR k
= j
+ 1 TO ShapeCount
dx = Shape(j).CtrMass.x - Shape(k).CtrMass.x
dy = Shape(j).CtrMass.y - Shape(k).CtrMass.y
dr
= SQR(dx
* dx
+ dy
* dy
) IF (dr
< 1.15 * (Shape
(j
).Diameter
+ Shape
(k
).Diameter
)) THEN ProximalPairsCount = ProximalPairsCount + 1
ProximalPairs(ProximalPairsCount, 1) = j
ProximalPairs(ProximalPairsCount, 2) = k
Shape1 = j
Shape2 = k
IF (ProximalPairsCount
> 0) THEN FOR n
= 1 TO ProximalPairsCount
Shape1 = ProximalPairs(n, 1)
Shape2 = ProximalPairs(n, 2)
' Collision detection
rmin = 999 ^ 999
ClosestIndex1 = 0
ClosestIndex2 = 0
FOR j
= 1 TO Shape
(Shape1
).Elements
FOR k
= 1 TO Shape
(Shape2
).Elements
dx = PointChain(Shape1, j).x - PointChain(Shape2, k).x
dy = PointChain(Shape1, j).y - PointChain(Shape2, k).y
r2 = dx * dx + dy * dy
rmin = r2
ClosestIndex1 = j
ClosestIndex2 = k
CollisionCount = CollisionCount + 1
' Normal vector 1
x0 = PointChain(Shape1, ClosestIndex1).x
y0 = PointChain(Shape1, ClosestIndex1).y
'CALL ccircle(x0, y0, 3, Shape(Shape1).Shade)
xx = CalculateNormalY(Shape1, ClosestIndex1)
yy = -CalculateNormalX(Shape1, ClosestIndex1)
norm
= SQR(xx
* xx
+ yy
* yy
) xx = xx / norm
yy = yy / norm
nx1 = xx
ny1 = yy
'CALL cline(x0, y0, x0 + nx1 * 15, y0 + ny1 * 15, Shape(Shape1).Shade)
' Normal vector 2
x0 = PointChain(Shape2, ClosestIndex2).x
y0 = PointChain(Shape2, ClosestIndex2).y
'CALL ccircle(x0, y0, 3, Shape(Shape2).Shade)
xx = CalculateNormalY(Shape2, ClosestIndex2)
yy = -CalculateNormalX(Shape2, ClosestIndex2)
norm
= SQR(xx
* xx
+ yy
* yy
) xx = xx / norm
yy = yy / norm
nx2 = xx
ny2 = yy
'CALL cline(x0, y0, x0 + nx2 * 15, y0 + ny2 * 15, Shape(Shape2).Shade)
' Perpendicular vector 1
dx1 = PointChain(Shape1, ClosestIndex1).x - Shape(Shape1).CtrRot.x
dy1 = PointChain(Shape1, ClosestIndex1).y - Shape(Shape1).CtrRot.y
px1 = -dy1
py1 = dx1
p1
= SQR(px1
* px1
+ py1
* py1
) px1 = px1 / p1
py1 = py1 / p1
'CALL cline(PointChain(Shape1, ClosestIndex1).x, PointChain(Shape1, ClosestIndex1).y, PointChain(Shape1, ClosestIndex1).x + px1 * 15, PointChain(Shape1, ClosestIndex1).y + py1 * 15, Shape(Shape1).Shade)
' Perpendicular vector 2
dx2 = PointChain(Shape2, ClosestIndex2).x - Shape(Shape2).CtrRot.x
dy2 = PointChain(Shape2, ClosestIndex2).y - Shape(Shape2).CtrRot.y
px2 = -dy2
py2 = dx2
p2
= SQR(px2
* px2
+ py2
* py2
) px2 = px2 / p2
py2 = py2 / p2
'CALL cline(PointChain(Shape2, ClosestIndex2).x, PointChain(Shape2, ClosestIndex2).y, PointChain(Shape2, ClosestIndex2).x + px2 * 15, PointChain(Shape2, ClosestIndex2).y + py2 * 15, Shape(Shape2).Shade)
' Angular velocity vector 1
w1 = Shape(Shape1).Omega
r1
= SQR(dx1
* dx1
+ dy1
* dy1
) vx1 = w1 * r1 * px1
vy1 = w1 * r1 * py1
'CALL cline(PointChain(Shape1, ClosestIndex1).x, PointChain(Shape1, ClosestIndex1).y, PointChain(Shape1, ClosestIndex1).x + vx1 * 5, PointChain(Shape1, ClosestIndex1).y + vy1 * 5, Shape(Shape1).Shade)
' Angular velocity vector 2
w2 = Shape(Shape2).Omega
r2
= SQR(dx2
* dx2
+ dy2
* dy2
) vx2 = w2 * r2 * px2
vy2 = w2 * r2 * py2
'CALL cline(PointChain(Shape2, ClosestIndex2).x, PointChain(Shape2, ClosestIndex2).y, PointChain(Shape2, ClosestIndex2).x + vx2 * 5, PointChain(Shape2, ClosestIndex2).y + vy2 * 5, Shape(Shape2).Shade)
' Mass terms
m1 = Shape(Shape1).Mass
i1 = Shape(Shape1).MOI
m2 = Shape(Shape2).Mass
i2 = Shape(Shape2).MOI
mu = 1 / (1 / m1 + 1 / m2)
' Velocity differential 1
vtx1 = Shape(Shape1).Velocity.x + vx1
vty1 = Shape(Shape1).Velocity.y + vy1
v1
= SQR(vtx1
* vtx1
+ vty1
* vty1
)
' Velocity differential 2
vtx2 = Shape(Shape2).Velocity.x + vx2
vty2 = Shape(Shape2).Velocity.y + vy2
v2
= SQR(vtx2
* vtx2
+ vty2
* vty2
)
' Velocity differential total
dvtx = vtx2 - vtx1
dvty = vty2 - vty1
' Geometry
n1dotdvt = nx1 * dvtx + ny1 * dvty
n2dotdvt = nx2 * dvtx + ny2 * dvty
' Momentum exchange
qx1 = nx1 * 2 * mu * n1dotdvt
qy1 = ny1 * 2 * mu * n1dotdvt
qx2 = nx2 * 2 * mu * n2dotdvt
qy2 = ny2 * 2 * mu * n2dotdvt
' Momentum exchange unit vector
q1
= SQR(qx1
* qx1
+ qy1
* qy1
) qhatx1 = qx1 / q1
qhaty1 = qy1 / q1
q2
= SQR(qx2
* qx2
+ qy2
* qy2
) qhatx2 = qx2 / q2
qhaty2 = qy2 / q2
' Undo previous motion
CALL RotShape
(Shape1
, Shape
(Shape1
).CtrRot
, -Shape
(Shape1
).Omega
) CALL RotShape
(Shape2
, Shape
(Shape2
).CtrRot
, -Shape
(Shape2
).Omega
) vtemp.x = -Shape(Shape1).Velocity.x
vtemp.y = -Shape(Shape1).Velocity.y
CALL TranslateShape
(Shape1
, vtemp
) vtemp.x = -Shape(Shape2).Velocity.x
vtemp.y = -Shape(Shape2).Velocity.y
CALL TranslateShape
(Shape2
, vtemp
)
' Separate along normal
vtemp.x = -nx1
vtemp.y = -ny1
CALL TranslateShape
(Shape1
, vtemp
) vtemp.x = -nx2
vtemp.y = -ny2
CALL TranslateShape
(Shape1
, vtemp
)
' Translational impulse
q1dotn1 = qhatx1 * nx1 + qhaty1 * ny1
q2dotn2 = qhatx2 * nx2 + qhaty2 * ny2
n1dotr1hat = (nx1 * dx1 + ny1 * dy1) / r1
n2dotr2hat = (nx2 * dx2 + ny2 * dy2) / r2
f1 = -q1dotn1 * n1dotr1hat
f2 = -q2dotn2 * n2dotr2hat
Shape(Shape1).Velocity.x = Shape(Shape1).Velocity.x + f1 * qx1 / m1
Shape(Shape1).Velocity.y = Shape(Shape1).Velocity.y + f1 * qy1 / m1
Shape(Shape2).Velocity.x = Shape(Shape2).Velocity.x + f2 * qx2 / m2
Shape(Shape2).Velocity.y = Shape(Shape2).Velocity.y + f2 * qy2 / m2
' Angular impulse
q1dotp1 = qx1 * px1 + qy1 * py1
q2dotp2 = qx2 * px2 + qy2 * py2
dw1 = r1 * q1dotp1 / i1
dw2 = -r2 * q2dotp2 / i2
CALL RotShape
(Shape1
, Shape
(Shape1
).CtrRot
, dw1
) CALL RotShape
(Shape2
, Shape
(Shape2
).CtrRot
, dw2
) Shape(Shape1).Omega = Shape(Shape1).Omega + dw1
Shape(Shape2).Omega = Shape(Shape2).Omega + dw2
' Dent along normal
PointChain(Shape1, ClosestIndex1).x = PointChain(Shape1, ClosestIndex1).x - 1 * nx1
PointChain(Shape1, ClosestIndex1).y = PointChain(Shape1, ClosestIndex1).y - 1 * ny1
PointChain(Shape2, ClosestIndex2).x = PointChain(Shape2, ClosestIndex2).x - 1 * nx2
PointChain(Shape2, ClosestIndex2).y = PointChain(Shape2, ClosestIndex2).y - 1 * ny2
'CALL SmoothShape(Shape1, Shape(Shape1).Elements, 1)
'CALL SmoothShape(Shape2, Shape(Shape2).Elements, 1)
' Static friction
IF Shape
(ShapeIndex
).Velocity.x
* Shape
(ShapeIndex
).Velocity.x
< .25 THEN Shape
(ShapeIndex
).Velocity.x
= Shape
(ShapeIndex
).Velocity.x
* .01 IF Shape
(ShapeIndex
).Velocity.y
* Shape
(ShapeIndex
).Velocity.y
< .25 THEN Shape
(ShapeIndex
).Velocity.y
= Shape
(ShapeIndex
).Velocity.y
* .01 IF Shape
(ShapeIndex
).Omega
* Shape
(ShapeIndex
).Omega
< .05 THEN Shape
(ShapeIndex
).Omega
= Shape
(ShapeIndex
).Omega
* .01
FOR ShapeIndex
= 1 TO ShapeCount
dx = Shape(ShapeIndex).CtrMass.x - Shape(ShapeIndex).CtrRot.x
dy = Shape(ShapeIndex).CtrMass.y - Shape(ShapeIndex).CtrRot.y
cx = Shape(ShapeIndex).CtrMass.x
cy = Shape(ShapeIndex).CtrMass.y
Gravity.x = -cx / 20
Gravity.y = -cy / 20
'torque = dx * Gravity.y - dy * Gravity.x
'Shape(ShapeIndex).Omega = Shape(ShapeIndex).Omega + torque / Shape(ShapeIndex).MOI
' Rotation update
CALL RotShape
(ShapeIndex
, Shape
(ShapeIndex
).CtrRot
, Shape
(ShapeIndex
).Omega
)
' Velocity update
Shape(ShapeIndex).Velocity.x = Shape(ShapeIndex).Velocity.x + Gravity.x / Shape(ShapeIndex).Mass
Shape(ShapeIndex).Velocity.y = Shape(ShapeIndex).Velocity.y + Gravity.y / Shape(ShapeIndex).Mass
CALL TranslateShape
(ShapeIndex
, Shape
(ShapeIndex
).Velocity
)
' Damping
Shape(ShapeIndex).Velocity.x = Shape(ShapeIndex).Velocity.x * .975
Shape(ShapeIndex).Velocity.y = Shape(ShapeIndex).Velocity.y * .975
Shape(ShapeIndex).Omega = Shape(ShapeIndex).Omega * .975
FOR ShapeIndex
= 1 TO ShapeCount
LOCATE 1, 1:
PRINT "Press space to enable creative mode." FOR i
= 1 TO Shape
(ShapeIndex
).Elements
- 1 x1 = PointChain(ShapeIndex, i).x
y1 = PointChain(ShapeIndex, i).y
x2 = PointChain(ShapeIndex, i + 1).x
y2 = PointChain(ShapeIndex, i + 1).y
CALL cline
(x1
, y1
, x2
, y2
, Shape
(ShapeIndex
).Shade
) x1 = PointChain(ShapeIndex, Shape(ShapeIndex).Elements).x
y1 = PointChain(ShapeIndex, Shape(ShapeIndex).Elements).y
x2 = PointChain(ShapeIndex, 1).x
y2 = PointChain(ShapeIndex, 1).y
CALL cline
(x1
, y1
, x2
, y2
, Shape
(ShapeIndex
).Shade
) 'CALL ccircle(Shape(ShapeIndex).CtrMass.x, Shape(ShapeIndex).CtrMass.y, 3, Shape(ShapeIndex).Shade)
'CALL ccircle(Shape(ShapeIndex).CtrRot.x, Shape(ShapeIndex).CtrRot.y, 3, Shape(ShapeIndex).Shade)
'CALL cline(Shape(ShapeIndex).CtrMass.x, Shape(ShapeIndex).CtrMass.y, Shape(ShapeIndex).CtrRot.x, Shape(ShapeIndex).CtrRot.y, Shape(ShapeIndex).Shade)
'CALL cpaint(Shape(ShapeIndex).CtrMass.x, Shape(ShapeIndex).CtrMass.y, Shape(ShapeIndex).Shade, Shape(ShapeIndex).Shade)
'CALL cline(PointChain(Shape1, ClosestIndex1).x, PointChain(Shape1, ClosestIndex1).y, Shape(Shape1).CtrRot.x, Shape(Shape1).CtrRot.y, Shape(Shape1).Shade)
'CALL cline(PointChain(Shape2, ClosestIndex2).x, PointChain(Shape2, ClosestIndex2).y, Shape(Shape2).CtrRot.x, Shape(Shape2).CtrRot.y, Shape(Shape2).Shade)
li = i - 1
ri = i + 1
IF (i
= 1) THEN li
= Shape
(k
).Elements
IF (i
= Shape
(k
).Elements
) THEN ri
= 1 l.x = PointChain(k, li).x
r.x = PointChain(k, ri).x
dx = r.x - l.x
CalculateNormalX = dx
li = i - 1
ri = i + 1
IF (i
= 1) THEN li
= Shape
(k
).Elements
IF (i
= Shape
(k
).Elements
) THEN ri
= 1 l.y = PointChain(k, li).y
r.y = PointChain(k, ri).y
dy = r.y - l.y
CalculateNormalY = dy
xx = 0
yy = 0
FOR i
= 1 TO Shape
(k
).Elements
xx = xx + PointChain(k, i).x
yy = yy + PointChain(k, i).y
Shape(k).CtrMass.x = xx / Shape(k).Elements
Shape(k).CtrMass.y = yy / Shape(k).Elements
r2max = -1
FOR i
= 1 TO Shape
(k
).Elements
xx = Shape(k).CtrMass.x - PointChain(k, i).x
yy = Shape(k).CtrMass.y - PointChain(k, i).y
r2 = xx * xx + yy * yy
r2max = r2
Shape
(k
).Diameter
= SQR(r2max
)
xx = 0
yy = 0
FOR i
= 1 TO Shape
(k
).Elements
xx = xx + (Shape(k).CtrRot.x - PointChain(k, i).x) ^ 2
yy = yy + (Shape(k).CtrRot.y - PointChain(k, i).y) ^ 2
Shape(k).MOI = (xx + yy) * (Shape(k).Mass / Shape(k).Elements)
FOR i
= 1 TO Shape
(k
).Elements
PointChain(k, i).x = PointChain(k, i).x + c.x
PointChain(k, i).y = PointChain(k, i).y + c.y
Shape(k).CtrRot.x = Shape(k).CtrRot.x + c.x
Shape(k).CtrRot.y = Shape(k).CtrRot.y + c.y
Shape(k).CtrMass.x = Shape(k).CtrMass.x + c.x
Shape(k).CtrMass.y = Shape(k).CtrMass.y + c.y
FOR i
= 1 TO Shape
(k
).Elements
xx = PointChain(k, i).x - c.x
yy = PointChain(k, i).y - c.y
PointChain
(k
, i
).x
= c.x
+ xx
* COS(da
) - yy
* SIN(da
) PointChain
(k
, i
).y
= c.y
+ yy
* COS(da
) + xx
* SIN(da
) xx = Shape(k).CtrMass.x - c.x
yy = Shape(k).CtrMass.y - c.y
Shape
(k
).CtrMass.x
= c.x
+ xx
* COS(da
) - yy
* SIN(da
) Shape
(k
).CtrMass.y
= c.y
+ yy
* COS(da
) + xx
* SIN(da
)
rawresolution = 7.5 ' Raw curve resolution.
targetpoints = 120 ' Number of points per curve.
smoothiterations = 15 ' Magnitude of smooth effect.
ShapeCount = ShapeCount + 1
numpoints = 0
xold = 999999
yold = 999999
' Gather raw data for one curve at a time.
' Click+drag mouse button 1 to trace out a curve.
delta
= SQR((x
- xold
) ^ 2 + (y
- yold
) ^ 2)
' Collect data only if the new point is sufficiently far away from the previous point.
IF (delta
> rawresolution
) AND (numpoints
< targetpoints
- 1) THEN numpoints = numpoints + 1
PointChain(ShapeCount, numpoints).x = x
PointChain(ShapeCount, numpoints).y = y
xold = x
yold = y
' If the curve contains less than the minimum numer of points, use interpolation to fill in the gaps.
DO WHILE (numpoints
< targetpoints
)
' Determine the pair of neighboring points that have the greatest separation of all pairs.
rad2max = -1
kmax = -1
FOR k
= 1 TO numpoints
- 1 xfac = PointChain(ShapeCount, k).x - PointChain(ShapeCount, k + 1).x
yfac = PointChain(ShapeCount, k).y - PointChain(ShapeCount, k + 1).y
rad2 = xfac ^ 2 + yfac ^ 2
kmax = k
rad2max = rad2
'''
cornercase = 0
xfac = PointChain(ShapeCount, numpoints).x - PointChain(ShapeCount, 1).x
yfac = PointChain(ShapeCount, numpoints).y - PointChain(ShapeCount, 1).y
rad2 = xfac ^ 2 + yfac ^ 2
kmax = numpoints
rad2max = rad2
cornercase = 1
'''
numpoints = numpoints + 1
' Starting next to kmax, create a `gap' by shifting all other points by one index.
PointChain(ShapeCount, j).x = PointChain(ShapeCount, j - 1).x
PointChain(ShapeCount, j).y = PointChain(ShapeCount, j - 1).y
' Fill the gap with a new point whose position is determined by the average of its neighbors.
PointChain(ShapeCount, kmax + 1).x = (1 / 2) * (PointChain(ShapeCount, kmax).x + PointChain(ShapeCount, kmax + 2).x)
PointChain(ShapeCount, kmax + 1).y = (1 / 2) * (PointChain(ShapeCount, kmax).y + PointChain(ShapeCount, kmax + 2).y)
numpoints = numpoints + 1
xx = PointChain(ShapeCount, numpoints - 1).x
yy = PointChain(ShapeCount, numpoints - 1).y
PointChain(ShapeCount, numpoints).x = (1 / 2) * (PointChain(ShapeCount, 1).x + xx)
PointChain(ShapeCount, numpoints).y = (1 / 2) * (PointChain(ShapeCount, 1).y + yy)
' At this stage, the curve still has all of its sharp edges. Use a `relaxation method' to smooth.
' The new position of a point is equal to the average position of its neighboring points.
CALL SmoothShape
(ShapeCount
, numpoints
, smoothiterations
)
Shape(ShapeCount).Elements = numpoints
Shape(ShapeCount).Mass = numpoints
Shape(ShapeCount).Velocity.x = 0
Shape(ShapeCount).Velocity.y = 0
Shape(ShapeCount).Omega = 0
CALL CalculateCtrMass
(ShapeCount
) Shape(ShapeCount).CtrRot.x = Shape(ShapeCount).CtrMass.x
Shape(ShapeCount).CtrRot.y = Shape(ShapeCount).CtrMass.y
CALL CalculateDiameter
(ShapeCount
) CALL CalculateMOI
(ShapeCount
)
TempChain(i, k).x = (1 / 2) * (PointChain(i, k - 1).x + PointChain(i, k + 1).x)
TempChain(i, k).y = (1 / 2) * (PointChain(i, k - 1).y + PointChain(i, k + 1).y)
PointChain(i, k).x = TempChain(i, k).x
PointChain(i, k).y = TempChain(i, k).y