Play a litle bit with physic.

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
D.J.Peters
Posts: 8631
Joined: May 28, 2005 3:28
Contact:

Play a litle bit with physic.

Post by D.J.Peters »

EDIT: short bug removed

Code: Select all

' D.J.Peters (Joshy)
const maxpoints      as integer = 120
const lastpoint      as integer = maxpoints - 1
const maxsprings     as integer = maxpoints + 1
const lastspring     as integer = maxsprings- 1

const pointkg        as single  = 1.0
const radius         as single  = 75.0
const stiffnes       as single  = 100.0
const damping        as single  = 10.0
const gravity        as single  = -9.81
const DT             as single  = 0.009
const FINAL_PRESSURE as single  = 100.0

const scr_w as integer=640
const scr_h as integer=480
const scr_w_half as integer=(scr_w-1)/2
const scr_h_half as integer=(scr_h-1)/2

type vector3d
  x as single
  y as single
  z as single
end type
type POINT3D
  position as VECTOR3D
  velocity as VECTOR3D
  force    as VECTOR3D
end type
type SPRING3D
  p1 as integer
  p2 as integer
  length as single
  normal as VECTOR3D
end type

dim shared as integer mb,mx,my,nearestpoint=0
dim shared as single pressure
dim shared as POINT3D points(maxpoints)
dim shared as SPRING3D springs(maxsprings)

sub createmesh()
  dim as integer i,p1,p2 
  dim as single  w
  w=6.28/(maxpoints-1)
  for i=0 to lastpoint
    with points(i).position
      .x=sin(i*w)*RADIUS
      .y=cos(i*w)*RADIUS
    end with
  next
  for i=0 to lastpoint
    springs(i).p1 = i
    springs(i).p2 = i+1
    springs(i).length = sqr((points(springs(i).p1).position.x - points(springs(i).p2).position.x) * (points(springs(i).p1).position.x - points(springs(i).p2).position.x) + _
                            (points(springs(i).p1).position.y - points(springs(i).p2).position.y) * (points(springs(i).p1).position.y - points(springs(i).p2).position.y) )
  next
  
  springs(i-1).p1 = lastpoint
  springs(i-1).p2 = 0
  springs(i-1).length = sqr((points(springs(i-1).p1).position.x - points(springs(i-1).p2).position.x) * (points(springs(i-1).p1).position.x - points(springs(i-1).p2).position.x) + _
                            (points(springs(i-1).p1).position.y - points(springs(i-1).p2).position.y) * (points(springs(i-1).p1).position.y - points(springs(i-1).p2).position.y) )
  
end sub

sub CalcForces()
  dim as integer i
  dim as VECTOR3D pointdiff,velocitydiff
  dim as single length,force,forcex,forcey,v,pv,direction
  
  for i=0 to lastpoint
    points(i).force.x = 0
    points(i).force.y = pointkg * GRAVITY
    if (Pressure - FINAL_PRESSURE) >= 0.0 then points(i).force.y*= (Pressure-final_pressure)
  next

  for i=0 to lastspring
    pointdiff.x=points(springs(i).p1).position.x - points(springs(i).p2).position.x
    pointdiff.y=points(springs(i).p1).position.y - points(springs(i).p2).position.y
    length=sqr(pointdiff.x*pointdiff.x + pointdiff.y*pointdiff.y)   	 
    if length<>0.0 then
      velocitydiff.x = points(springs(i).p1).velocity.x - points(springs(i).p2).velocity.x
      velocitydiff.y = points(springs(i).p1).velocity.y - points(springs(i).p2).velocity.y
      force= (length-springs(i).length)*stiffnes + (velocitydiff.x*pointdiff.x + velocitydiff.y * pointdiff.y) * damping/length
      forcex=pointdiff.x/length*force
      forcey=pointdiff.y/length*force 
      points(springs(i).p1).force.x-=forcex
      points(springs(i).p1).force.y-=forcey
      points(springs(i).p2).force.x+=forcex
      points(springs(i).p2).force.y+=forcey
    end if
    springs(i).normal.x = pointdiff.y/length '!!!
    springs(i).normal.y = -pointdiff.x/length '!!!			
  next

  for i=0 to lastspring-1
    pointdiff.x=points(springs(i).p1).position.x - points(springs(i).p2).position.x
    pointdiff.y=points(springs(i).p1).position.y - points(springs(i).p2).position.y
    length=sqr(pointdiff.x*pointdiff.x + pointdiff.y*pointdiff.y) 	
    v += 0.5 * abs(pointdiff.x) * abs(springs(i).normal.x) * length
  next

  for i=0 to lastspring-1
    pointdiff.x=points(springs(i).p1).position.x - points(springs(i).p2).position.x
    pointdiff.y=points(springs(i).p1).position.y - points(springs(i).p2).position.y
    length=sqr(pointdiff.x*pointdiff.x + pointdiff.y*pointdiff.y)
    pv=length*pressure*(1.0/v)
    points(springs(i).p1).force.x += springs(i).normal.x * pv
    points(springs(i).p1).force.y += springs(i).normal.y * pv
    points(springs(i).p2).force.x += springs(i).normal.x * pv
    points(springs(i).p2).force.y += springs(i).normal.y * pv
  next

  for i = 0 to lastpoint
    points(i).velocity.x+=( Points(i).force.x / pointkg )* DT
    direction=points(i).velocity.x * DT
    if (points(i).position.x + direction) < -scr_w_half then
      direction*=-1 
      points(i).velocity.x*= - 0.5 
      points(i).velocity.y*=  0.5
    elseif (points(i).position.x + direction) > scr_w_half then
      direction*=-1 
      points(i).velocity.x*= -0.5 
      points(i).velocity.y*=   0.5
    end if  
    points(i).position.x+=direction

    points(i).velocity.y+=( Points(i).force.y / pointkg )* DT
    direction=points(i).velocity.y * DT
    if (points(i).position.y + direction) < -scr_h_half then
      direction*=-1
      points(i).velocity.y*= - 0.5 
      points(i).velocity.x*=   0.5
    elseif (points(i).position.y + direction) > scr_h_half then
      direction*=-1
      points(i).velocity.y*= -0.5 
      points(i).velocity.x*=  0.5
    end if  
    points(i).position.y+=direction
  next
end sub

sub Euler()
  dim as integer i
  dim as single  direction
   for i = 0 to lastpoint
     points(i).velocity.x+=( Points(i).force.x / pointkg )* DT
     direction=points(i).velocity.x * DT
     if (points(i).position.x + direction) < -scr_w_half then
       direction*=-1 ' -scr_w_half - points( i ).position.x
       points(i).velocity.x*= - 0.5 
       points(i).velocity.y*=  0.9
     elseif (points(i).position.x + direction) > scr_w_half then
       direction*=-1 ' scr_w_half - points(i).position.x
       points(i).velocity.x*= - 0.5 
       points(i).velocity.y*=  0.9
     end if  
     points(i).position.x+=direction

     points(i).velocity.y+=( Points(i).force.y / pointkg )* DT
     direction=points(i).velocity.y * DT
     if (points(i).position.y + direction) < -scr_h_half then
       direction*=-1 ' -scr_h_half - points( i ).position.y
       'points(i).velocity.y*= - 0.5 
       points(i).velocity.x*=  0.9
     elseif (points(i).position.y + direction) > scr_h_half then
       direction*=-1 ' scr_h_half - points(i).position.y
       'points(i).velocity.y*= - 1.5 
       points(i).velocity.x*=  0.9
     end if  
     points(i).position.y+=direction
                
  next
end sub
sub DrawIt1()
  dim as integer i
  
    pset  (scr_w_half+points(0).position.x,scr_h_half-points(0).position.y)
  for i=1 to lastpoint
    line -(scr_w_half+points(i).position.x,scr_h_half-points(i).position.y)
  next
    line -(scr_w_half+points(0).position.x,scr_h_half-points(0).position.y)
end sub
sub DrawIt2()
  dim as integer i
  for i=0 to lastspring-1
    line (scr_w_half+points(springs(i).p1).position.x,scr_h_half-points(springs(i).p1).position.y)-(scr_w_half+points(springs(i).p2).position.x,scr_h_half-points(springs(i).p2).position.y),i and &HFF
  next
end sub
'
'main
'
dim as integer frames,wpage,vpage=1
dim as single t1,t2

createmesh
t1=timer
screenres scr_w,scr_h,8,2
while len(inkey)=0
  if pressure<final_pressure then pressure+=(final_pressure/300.0)
  CalcForces
  screenset wpage,vpage
  swap wpage,vpage
  cls
  drawIt1
  t2=timer
  frames+=1
  if (t2-t1)>1 then 
    windowtitle "FPS="+str(frames)
    t1=t2:frames=0
  end if
wend
sleep
Last edited by D.J.Peters on Mar 13, 2008 12:19, edited 4 times in total.
SotSvart
Posts: 262
Joined: May 27, 2005 9:03
Location: Norway
Contact:

Post by SotSvart »

Thats great.. I have no idea how you did it, but it looks great =)
jofers
Posts: 1525
Joined: May 27, 2005 17:18

Post by jofers »

Cool... love the slow-motion "wiggle-ripple-tronics"
D.J.Peters
Posts: 8631
Joined: May 28, 2005 3:28
Contact:

Post by D.J.Peters »

play with the const and you can see what happents
but change the values not so hard less is often more ;-)
numofpoints = 5 'an jumping box for example
try to change stiffness, final_pressure and so on ...
What are you get for FPS on my box 800-900 it can't be what is wrong with the FPS counter?

Joshy
Is velocity right in english?
Last edited by D.J.Peters on Mar 13, 2008 12:41, edited 1 time in total.
jofers
Posts: 1525
Joined: May 27, 2005 17:18

Post by jofers »

In physics, yeah. Velocity can be positive or negative. "Speed" is a velocity's magnitude, like if the velocity is -2m/s in such-and-such direction, then the speed is just 2m/s.
jupiter3888
Posts: 103
Joined: Jun 30, 2005 3:54
Location: adelaide, australia
Contact:

Post by jupiter3888 »

im gettin around 1000 FPS on a 2.8ghz intel celeron.
i like the effects to!
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

1. ) HOLY CRAP! Wtf!? How did you learn to do something like this!? I've been messing with the constants and getting amazing effects......


I am soooooo psyched out right now. The fact that you built it so it runs on those variables as if it were real physics amazes me. You can actually change them as you would in an experiment and see what happens.

2. ) Any way you can make a filler or other options for this amazing program? Or at least tell me where you learned physics like that.



3.) Can I ask you something else too? Why is the program so fast? If I was to run that many variables with line putting in a program it wouldn't go anywhere near that fast. Does option explicit do that for you or something? Please tell me.

4.) I wasn't expecting to make a 4th comment, but I'd like to know something....

Code: Select all

line -(scr_w_half+points(i).position.x,scr_h_half-points(i).position.y) 
Um....that line statement, is that "-" before the values are called making the line from the last point drawn or something?
steven522
Posts: 265
Joined: May 27, 2005 13:02
Location: Alabama, USA
Contact:

Post by steven522 »

The screen says 560 to 580 FPS, but the animation is extremely "jerky". It rolls smoothly for a second, "freezes" for a second, rolls smoothly, freeze, smooth, ...

EDIT:
If I remove the TIMER and FPS calc and display, I get extremely smooth animation for the entire run.
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

Steven, I noticed that too. I think it's because FreeBasic's changing the process for the window when you change it's title. That slows it down a bit. I still don't have any answers on why it's so fast though.
mambazo
Posts: 652
Joined: Jul 17, 2005 13:02
Location: Ireland
Contact:

Post by mambazo »

Wow, this is excellant! Reminds me about a ridgid body dynamics simulator I wrote years ago in QB that got lost in the Storm that is XP (lost a 50GB partition! still unusable *sigh*).

BUT! For anyone wanting the documents I used as a reference, I can post them up here. 3 or 4 pdf's explaining how to simulate real physics collisions in both 2D and 3D using the ACTUAL formulas from physics!
mjs
Site Admin
Posts: 842
Joined: Jun 16, 2005 19:50
Location: Germany

Post by mjs »

Yes, please post the links to the documents here. I'm interested in those documents.

Regards,
Mark
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

I have to thank the excellent FPS counter on this program. I just realized my program's running an average of 30 fps, not 60 fps like I previously thought.

The reason I thought it was 60 fps is because the timer based system must have had a few errors in it. Hmm. ^_^

What I need to know now, it why this program's so fast and mine's only running 30 fps.

EDIT: I'm able to get my programs around 70 fps if I take away my screeensync, but I like that. Heh...I could still use some speed hints.
D.J.Peters
Posts: 8631
Joined: May 28, 2005 3:28
Contact:

Post by D.J.Peters »

Hello mambazo,
i have make tests with springs for FreeSpeedRacer the part of shock absorber computation
and found doc's on dynymic soft-body the math for the pressure forces.
Do you mean this too?

Here the Link to an how to pdf file only in 2D too.
http://panoramix.ift.uni.wroc.pl/~maq/s ... ftbody.pdf
but only the volume math will be included iin FreeSpeedRacer.

Joshy
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Post by anonymous1337 »

Umm...D.J.Peters, thank you for that FPS counter. I'm now able to strictly control my frames per second without using screensync _that sometimes slows down the program_

I do this by saying if frames < 60 then movecontrols and print screen.

It's really nice that you posted that. I learned a lot from it. Although I still can't write a program that goes as fast as yours, and I have to use screenlock to do it, it's helped me understand FPS and data constants better.

Always thankful,
anonymous1337
mambazo
Posts: 652
Joined: Jul 17, 2005 13:02
Location: Ireland
Contact:

Post by mambazo »

for anyone who wanted some reference material regarding real physics simulation... here is the link!

http://www.langfordtavern.com/dev/media ... hysics.zip

takes a LONG time to figure out how to use it, but its the most comprehensive reference I ever found.
Post Reply