Author Topic: Ah Spring!  (Read 5958 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Ah Spring!
« on: August 04, 2020, 08:34:40 pm »
Ken had me wondering about spring things:

Ball Bearing Springs:
Code: QB64: [Select]
  1. _TITLE "simple spring" 'b+ 2020-08-04
  2. 'from: "Mouse down, drag ball, release...  Boing" 'B+ 2019-01-08 from
  3. 'from: boing.bas for SmallBASIC 2015-07-25 MGA/B+
  4. '2020-08-04 overhaul completely to use 3D spheres instead of lines horizontally across the screen.
  5. '           103 fixes to make look almost right
  6.  
  7. CONST xmax = 1000
  8. CONST ymax = 700
  9. SCREEN _NEWIMAGE(xmax, ymax, 32)
  10. _DELAY .25
  11.  
  12. COLOR , &H884444
  13.  
  14. PRINT "Building spring from spheres hopefully to get 3D coloring effect."
  15. PRINT "Check a 250 pixel radius sphere centered on screen, press any to continue..."
  16. drawBB 500, 350, 250 'check a good sized sphere
  17.  
  18. '            discover by experiment how to draw a spring with control over variables
  19. y = _HEIGHT / 2 ' through middle vertically
  20. radius = 100
  21. da = _PI(2 / radius)
  22. astart = _PI(-.5): astop = _PI(3 / 2) + 2 * da ' so spring starts and ends at 12 o'clock on screen
  23.  
  24. winds = 10
  25. x = -2 * radius
  26. FOR a = astart TO astop + (winds + 2) * _PI(2) STEP da
  27.     sx = x + radius * COS(a)
  28.     sy = y + radius * SIN(a)
  29.     drawBB sx, sy, 6
  30.     x = x + 1 'dx at 1 is perfect for moving 1 radius amount to right in one wind
  31. PRINT x; "OK x advances exactly 1 radius amount for every 1 wind or circle cycle of angle. "
  32. PRINT "Press any to continue..."
  33.  
  34. 'OK to get twice the winds, same radius reduce dx by .5
  35. winds = 20
  36. x = -2 * radius
  37. FOR a = astart TO astop + (winds + 6) * _PI(2) STEP da 'need extra winds to show partials from loops to right
  38.     sx = x + radius * COS(a)
  39.     sy = y + radius * SIN(a)
  40.     drawBB sx, sy, 6
  41.     x = x + .5 'cut dx in half
  42. PRINT x; "OK 20 winds, dx = .5 covers screen. "
  43. PRINT "Press any to continue..."
  44.  
  45. 'OK to get 1/5 the winds 2 now, increase dx to 5
  46. winds = 2
  47. x = -2 * radius
  48. FOR a = astart TO astop + (winds) * _PI(2) STEP da 'no extra winds needed
  49.     sx = x + radius * COS(a)
  50.     sy = y + radius * SIN(a)
  51.     drawBB sx, sy, 6
  52.     x = x + 5 'cut dx in half
  53. PRINT x; "OK 2 winds, dx = 5 covers screen. "
  54. PRINT "Press any to continue..."
  55.  
  56. ' OK do we have enough to make the spring springgy
  57. _TITLE "Simple spring in action!  press esc to quit..."
  58. wDir = .1: winds = 10: dx = 1
  59. DO 'stretch and compact spring
  60.     CLS
  61.     x = -2 * radius
  62.     FOR a = astart TO astop + (winds + 13) * _PI(2) STEP da 'have to go way past right border with winds!
  63.         sx = x + radius * COS(a)
  64.         sy = y + radius * SIN(a)
  65.         drawBB sx, sy, 6
  66.         x = x + dx 'cut dx in half
  67.     NEXT
  68.     _DISPLAY
  69.     _LIMIT 30
  70.     winds = winds + wDir
  71.     IF winds > 40 THEN winds = 40: wDir = -wDir
  72.     IF winds < 2 THEN winds = 2: wDir = -wDir
  73.     m = winds / 10
  74.     dx = 1 / m
  75.  
  76. SUB drawBB (x, y, r) 'this is metal steel ball  needs fcirc
  77.     DIM i, dcdr
  78.     dcdr = 255 / r
  79.     FOR i = r TO 0 STEP -.5
  80.         fcirc x + i / 2 - r / 2, y + i / 2 - r / 2, i, _RGB32(255 - dcdr * i)
  81.     NEXT
  82.  
  83. 'from Steve Gold standard
  84. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  85.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  86.     DIM X AS INTEGER, Y AS INTEGER
  87.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  88.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  89.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  90.     WHILE X > Y
  91.         RadiusError = RadiusError + Y * 2 + 1
  92.         IF RadiusError >= 0 THEN
  93.             IF X <> Y + 1 THEN
  94.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  95.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  96.             END IF
  97.             X = X - 1
  98.             RadiusError = RadiusError - X * 2
  99.         END IF
  100.         Y = Y + 1
  101.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  102.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  103.     WEND
  104.  
  105.  

And metal with weird lighting:
Code: QB64: [Select]
  1. _TITLE "simple spring 2020-08-04" 'b+ 2020-08-04
  2. 'from: "Mouse down, drag ball, release...  Boing" 'B+ 2019-01-08 from
  3. 'from: boing.bas for SmallBASIC 2015-07-25 MGA/B+
  4. ' 2020-08-04 overhaul completely to use 3D spheres instead of lines horizontally across the screen.
  5. '           103 fixes to make look almost right
  6. ' 2020-08-04 not really liking the spheres, try lines again.
  7.  
  8. CONST xmax = 1000
  9. CONST ymax = 700
  10. SCREEN _NEWIMAGE(xmax, ymax, 32)
  11. _DELAY .25
  12. COLOR , &H9999BB
  13. '            discover by experiment how to draw a spring with control over variables
  14. y = _HEIGHT / 2 ' through middle vertically
  15. radius = 100
  16. da = .1 * _PI(2 / radius)
  17. astart = _PI(-.5): astop = _PI(3 / 2) + 2 * da ' so spring starts and ends at 12 o'clock on screen
  18.  
  19. winds = 10
  20. x = -2 * radius
  21. FOR a = astart TO astop + (winds + 2) * _PI(2) STEP da
  22.     sx = x + radius * COS(a)
  23.     sy = y + radius * SIN(a)
  24.     FOR dy = 6 TO 0 STEP -.5
  25.         LINE (sx, sy + dy)-(sx + 6, sy + dy), _RGB32(185 - dy * 17), BF
  26.     NEXT
  27.     x = x + .1 'dx at 1 is perfect for moving 1 radius amount to right in one wind
  28. PRINT x; "OK x advances exactly 1 radius amount for every 1 wind or circle cycle of angle. "
  29. PRINT "Press any to continue..."
  30.  
  31. 'OK to get twice the winds, same radius reduce dx by .5
  32. winds = 20
  33. x = -2 * radius
  34. FOR a = astart TO astop + (winds + 6) * _PI(2) STEP da 'need extra winds to show partials from loops to right
  35.     sx = x + radius * COS(a)
  36.     sy = y + radius * SIN(a)
  37.     FOR dy = 6 TO 0 STEP -.5
  38.         LINE (sx, sy + dy)-(sx + 6, sy + dy), _RGB32(185 - dy * 17), BF
  39.     NEXT
  40.     x = x + .05 'cut dx in half
  41. PRINT x; "OK 20 winds, dx = .5 covers screen. "
  42. PRINT "Press any to continue..."
  43.  
  44. 'OK to get 1/5 the winds 2 now, increase dx to 5
  45. winds = 2
  46. x = -2 * radius
  47. FOR a = astart TO astop + winds * _PI(2) STEP da 'no extra winds needed
  48.     sx = x + radius * COS(a)
  49.     sy = y + radius * SIN(a)
  50.     FOR dy = 6 TO 0 STEP -.5
  51.         LINE (sx, sy + dy)-(sx + 6, sy + dy), _RGB32(185 - dy * 17), BF
  52.     NEXT
  53.     x = x + .5 'cut dx in half
  54. PRINT x; "OK 2 winds, dx = 5 covers screen. "
  55. PRINT "Press any to continue..."
  56.  
  57. ' OK do we have enough to make the spring springgy
  58. _TITLE "Simple spring in action!  press esc to quit..."
  59. wDir = .1: winds = 10: dx = 1
  60. DO 'stretch and compact spring
  61.     CLS
  62.     x = -2 * radius
  63.     FOR a = astart TO astop + (winds + 13) * _PI(2) STEP da 'have to go way past right border with winds!
  64.         sx = x + radius * COS(a)
  65.         sy = y + radius * SIN(a)
  66.         FOR dy = 6 TO 0 STEP -.5
  67.             LINE (sx, sy + dy)-(sx + 6, sy + dy), _RGB32(185 - dy * 17), BF
  68.         NEXT
  69.         x = x + dx 'cut dx in half
  70.     NEXT
  71.     _DISPLAY
  72.     _LIMIT 30
  73.     winds = winds + wDir
  74.     IF winds > 40 THEN winds = 40: wDir = -wDir
  75.     IF winds < 2 THEN winds = 2: wDir = -wDir
  76.     m = winds / 10
  77.     dx = .1 * (1 / m)
  78.  
  79.  

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #1 on: August 04, 2020, 10:18:47 pm »
Those are INCREDIBLE! That does something that I tried to do but couldn't figure out, connecting each end of the spiral. Mine don't connect at the ends. I might try to learn from this. Thanks!

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Ah Spring!
« Reply #2 on: August 04, 2020, 10:59:17 pm »
I agree. Incredible... But do they come in blue? Nah. Kidding... great job!
Logic is the beginning of wisdom.

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #3 on: August 04, 2020, 11:25:10 pm »
Here is my spring version that's animated. I have no idea how this was made, just playing with numbers really and my old spiral code again. I'll post a picture below but it doesn't really show what it does.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. st = -.125
  3. st2 = 1
  4. tt = .25
  5.  
  6.     FOR d = 150 TO 0 STEP -.125
  7.         s = s + 10 + tt
  8.         t = t + tt
  9.         x = (COS(s * 3.141592 / 180) * d) + t
  10.         y = SIN(s * 3.141592 / 180) * d
  11.         FOR sz = .25 TO 3 STEP .25
  12.             CIRCLE (x + 150, y + 300), sz, _RGB32(255, 255, 255)
  13.         NEXT sz
  14.         c = 0
  15.     NEXT d
  16.     _DELAY .03
  17.     IF st2 = 1 THEN tt = tt - .01
  18.     IF st2 = 2 THEN tt = tt + .1
  19.     IF tt < 0 THEN st2 = 2
  20.     IF tt > .5 THEN st2 = 1
  21.     s = 0
  22.     t = 0
  23.     _DISPLAY
  24.     CLS
  25.  

Kens Spring.jpg
* Kens Spring.jpg (Filesize: 107.27 KB, Dimensions: 805x617, Views: 192)
« Last Edit: August 04, 2020, 11:29:43 pm by SierraKen »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #4 on: August 04, 2020, 11:27:01 pm »
Here is a regular animated spiral spring I made before the last one.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 600, 32)
  2. st = -.125
  3. st2 = 1
  4. tt = .25
  5.  
  6.     FOR d = 150 TO 0 STEP -.125
  7.         s = s + 1 + tt
  8.         t = t + tt
  9.         x = (COS(s * 3.141592 / 180) * d) + t
  10.         y = SIN(s * 3.141592 / 180) * d
  11.         FOR sz = .25 TO 3 STEP .25
  12.             c = c + 25
  13.             CIRCLE (x + 450, y + 300), sz, _RGB32(c, c, c)
  14.         NEXT sz
  15.         c = 0
  16.     NEXT d
  17.     _DELAY .03
  18.     IF st2 = 1 THEN tt = tt - .01
  19.     IF st2 = 2 THEN tt = tt + .01
  20.     IF tt < -.5 THEN st2 = 2
  21.     IF tt > .5 THEN st2 = 1
  22.     s = 0
  23.     t = 0
  24.     _DISPLAY
  25.     CLS
  26.  
Ken's Spring 2.jpg
* Ken's Spring 2.jpg (Filesize: 46.79 KB, Dimensions: 998x625, Views: 216)
« Last Edit: August 04, 2020, 11:29:24 pm by SierraKen »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Ah Spring!
« Reply #5 on: August 04, 2020, 11:42:46 pm »
Hey Ken the cone thing was neat and the spiral spring is it!, just make d constant at some radius for a cylinder spring.

Basically just calculate points for circle but move the x, y center of the circle as you calculate points.

points of a circle at radius r and x, y center is

for a = 0 to 2*pi * (how many circles it takes)
  sx = x + r * cos(a)
  sy = y + r * sin(a)
  change x and/or y for spring
next a



Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #6 on: August 05, 2020, 01:05:10 am »
Awesome! Now I have new way to make circles. I just made a regular spring, it's not perfect but it's as good as I can do.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. pi = _PI
  3. y = 100
  4. r = 50
  5. xx = 2
  6. x2 = 1
  7. x3 = 300
  8.     FOR x = 100 TO x3 STEP xx
  9.         FOR a = 0 TO 2 * pi * 50
  10.             sx = x + r * COS(a)
  11.             sy = y + r * SIN(a)
  12.             CIRCLE (sx, sy), 2, _RGB32(255, 255, 255)
  13.         NEXT a
  14.     NEXT x
  15.     IF xx > 80 THEN x2 = 2
  16.     IF xx < 20 THEN x2 = 1
  17.     IF x2 = 1 THEN xx = xx + 2: x3 = x3 + 10
  18.     IF x2 = 2 THEN xx = xx - 2: x3 = x3 - 10
  19.     _DELAY .1
  20.     _DISPLAY
  21.     CLS
  22.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Ah Spring!
« Reply #7 on: August 05, 2020, 01:42:32 am »
Here's something simpler for you tweak numbers. You just needed to move x while "drawing circle", at same time.
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2. pi = _PI  'constant
  3. y = 300  'constant for now
  4. r = 50    'constant for now for cylinder springs
  5. FOR a = 0 TO 2 * pi * 16 STEP 2 * pi / 360  ' stepping 1 degree, a circle = 2*pi divide by 360 = 1 degree
  6.     sx = x + r * COS(a)
  7.     sy = y + r * SIN(a)
  8.     IF a > 0 THEN LINE (lastsx, lastsy)-(sx, sy), _RGB32(255, 255, 255) ' a>0 because you need a lastsx, lastxy
  9.     lastsx = sx: lastsy = sy
  10.     x = x + .1
  11.     _LIMIT 200
  12.  
  13.  
  14.  
  15.  
  16.  
« Last Edit: August 05, 2020, 01:43:46 am by bplus »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Ah Spring!
« Reply #8 on: August 05, 2020, 09:54:33 am »
@bplus I tried

Code: QB64: [Select]
  1. DEFINT A-Z
  2.  
  3. CONST z0 = 2500
  4. CONST y0 = -200
  5. CONST d = 700
  6.  
  7. CONST sw = 640
  8. CONST sh = 480
  9.  
  10. pi = 4 * ATN(1)
  11.  
  12. SCREEN _NEWIMAGE(sw, sh, 32)
  13.  
  14.  
  15. t = 0
  16.     t = t + 0.1
  17.     h = 120 + 100 * SIN(t)
  18.  
  19.     LINE (0, 0)-(sw, sh), _RGB(0, 0, 0), BF
  20.  
  21.     ox = 500 * COS(0)
  22.     oz = 500 * SIN(0)
  23.     oy = -500 + 0 * h / (2 * pi)
  24.     'PSET (sw / 2 + ox * d / (oz + z0), sh / 2 - (oy + y0) * d / (oz + z0))
  25.  
  26.     FOR a = 0.1 TO 15 * 2 * pi STEP 0.1
  27.         x = 500 * COS(a)
  28.         z = 500 * SIN(a)
  29.         y = -500 + a * h / (2 * pi)
  30.  
  31.         DIM dy AS SINGLE
  32.         FOR dy = 6 TO 0 STEP -.5
  33.             LINE (sw / 2 + ox * d / (oz + z0), sh / 2 - (oy + y0) * d / (oz + z0) + dy)-(sw / 2 + x * d / (z + z0) + 6, sh / 2 - (y + y0) * d / (z + z0) + dy), _RGB32(185 - dy * 17), BF
  34.         NEXT
  35.  
  36.         ox = x
  37.         oy = y
  38.         oz = z
  39.     NEXT
  40.  
  41.     _DISPLAY
  42.     _LIMIT 30
  43.  


no shading
Code: [Select]
defint a-z

const z0 = 2500
const y0 = -200

const d = 700

const sw = 640
const sh = 480

dim shared pi as double
pi = 4*atn(1)

screen _newimage(sw, sh, 32)

dim a as double
dim t as double
t = 0

r = 400
rr = 1000

do
    t = t + 0.1
    h = 120 + 100*sin(t)

    line (0, 0)-(sw, sh), _rgb(0, 0, 0), bf

    oy = -500 + 0*h/(2*pi)
    ox = r*cos(0)
    oz = r*sin(0)

    for a = 0.1 to 15*2*pi step 0.1
        y = -500 + a*h/(2*pi)
        x = r*cos(a)
        z = r*sin(a)

ou = sw/4 + ox*d/(oz + z0)
ov = sh/2 - (oy + y0)*d/(oz + z0)

u = sw/4 + x*d/(z + z0)
v = sh/2 - (y + y0)*d/(z + z0)
line (ou, ov)-(u, v)

        ox = x
        oy = y
        oz = z
    next

    _display
    _limit 20
loop until _keyhit = 27
system
« Last Edit: August 06, 2020, 02:34:43 am by _vince »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Ah Spring!
« Reply #9 on: August 05, 2020, 11:10:16 am »
Nice one @_vince

That was what I was going for next showing both ends with set amount of coils contacting and expanding, your perspective is better too!

Oh hey, you have 3D thing going!

I can close those gaps in back by making the STEP .01 and that shows coloring better too.
« Last Edit: August 05, 2020, 11:24:19 am by bplus »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #10 on: August 05, 2020, 12:18:48 pm »
I haven't tried Vince's yet, but I just made your simple version, b+, into a bouncy spring.

Code: QB64: [Select]
  1. 'Spring by B+, mod by SierraKen
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. pi = _PI 'constant
  4. y = 300 'constant for now
  5. r = 50 'constant for now for cylinder springs
  6. xx = .01
  7. xx2 = 1
  8.     _LIMIT 7
  9.     FOR a = 0 TO 2 * pi * 16 STEP 2 * pi / 360 ' stepping 1 degree, a circle = 2*pi divide by 360 = 1 degree
  10.         sx = x + r * COS(a)
  11.         sy = y + r * SIN(a)
  12.         IF a > 0 THEN LINE (lastsx, lastsy)-(sx, sy), _RGB32(255, 255, 255) ' a>0 because you need a lastsx, lastxy
  13.         lastsx = sx: lastsy = sy
  14.         x = x + xx
  15.     NEXT a
  16.     _DISPLAY
  17.     CLS
  18.     x = 0
  19.     IF xx > .25 THEN xx2 = 2
  20.     IF xx < .01 THEN xx2 = 1
  21.     IF xx2 = 1 THEN xx = xx + .025
  22.     IF xx2 = 2 THEN xx = xx - .025
  23.  
« Last Edit: August 05, 2020, 12:20:06 pm by SierraKen »

Offline SierraKen

  • Forum Resident
  • Posts: 1454
    • View Profile
Re: Ah Spring!
« Reply #11 on: August 05, 2020, 12:20:24 pm »
That looks amazing Vince!

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Ah Spring!
« Reply #12 on: August 05, 2020, 01:18:05 pm »
now lets have it crawl down a set of 3D stairs

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Ah Spring!
« Reply #13 on: August 05, 2020, 01:53:11 pm »
Nice mod Ken :)

@_vince that 3D approach might be just the thing for me to study. I learned how to use SIN and COS (for computer graphics) from a little snippet for drawing a hexagon 5+ years ago.

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Ah Spring!
« Reply #14 on: August 05, 2020, 02:05:28 pm »
The projection used here is proper 3D and the coordinates are calculated with the similar triangle method: eye to screen to object. Plenty of tutorials on the matter, but in short:

if (x, y, z) is the 3D coordinate, where z axis is pointing into the screen, projecting to 2D coordinate (u, v) I do as follows:

u = x*d/(z + z0)
v = y*d/(z + z0)

then you must select d and z0 to whatever looks right. In my programs I've used d = 700 and z0 = 2500

The easiest way to do 3D is parallel projection:

u = x + d*z
v = y + d*z

where, again, pick d to something that looks right. Here, I usually use d = 0.7

I used my hyperboloid animation from a while ago as a reference to draw the spiral here, using similar values for projection.

These methods are easy enough for simple wireframe type drawings but things get a lot more complicated when you want hidden lines, objects behind camera, complex rotation, etc. In that case the easiest thing is to just learn OpenGL.