Basic Physics Engine.. WIP

Community Forums/Showcase/Basic Physics Engine.. WIP

Nate the Great(Posted 2009) [#1]
Hi

I made a little physics engine in bmax as a small first project and it turned out to be quite succesful! It is still very much a WIP but I am improving on it daily. Sorry there are no screenies ATM. maybe I will post some tomorrow if I have time. Please post how many boxes your comp can handle without significant slowdown.

controls:
arrows:move one of the starter verlets.. cant remember wich one
space bar: add a box!
mouse: click to grab the nearest verlet!

friction test: most recent linky
http://naillproductions.synthasite.com/resources/NTG%20physics%20engine%20(2).zip

edit: here is a screenie!




slenkar(Posted 2009) [#2]
pretty good so far
I could add about 6 boxes with a 2.5ghz celeron


Nate the Great(Posted 2009) [#3]
only 6 boxes?!? thats um.. a little lower than I expected... I can get around 30 boxes


plash(Posted 2009) [#4]
Quite slow when spawning boxes here too.


Warpy(Posted 2009) [#5]
I started noticing some jitters fairly early too, at around 12 boxes.


Nate the Great(Posted 2009) [#6]
hmmm im not sure what the jitters are, I have noticed them too. Maybe it is my inexperience with frame limiting in bmax? I simply use graphics 800,600,0,60 and asume it does the rest. Am I right to assume that or must I do something else? If I am doing everything else right I might have accidentally made my engine unstable. :p

each box is 8 verlets and 14 constraints so that may also explain it.


Gabriel(Posted 2009) [#7]
No, you can't just set the graphics mode and hope it does the rest. You need a proper timing solution, and since you're doing verlet integration you'll need to have a fixed timestep. You probably already have a fixed timestep if you're doing nothing for timing, but you'll need to keep it when you integrate a timing solution. QuickSilva has a thread going on the subject in the BlitzMax beginners forum if you want to read up.


Nate the Great(Posted 2009) [#8]
thanks.. hmm for some reason I thought that blitz max somhow controled the frame rate with the flip command

Ill look into a timing solution. Thanks Gabriel


Gabriel(Posted 2009) [#9]
Well if VSync is enabled, it kind of will, but it's dependant upon your code running fast enough for VSync to work. If your code isn't (always) done before the next VSync, it will jerk. Also, if someone happens to have VSync disabled, it's just not going to happen.


Nate the Great(Posted 2009) [#10]
Ok I think I get it. I have also rooted out the slowdown. I had it on 25 iterations in the constraint loop! oops :p


Nate the Great(Posted 2009) [#11]
hmmm this is odd.. I have used waittimer for a quick way to mess around with fps and time steps but it seems even with waittimer my minimum fps is 11 and maximum fps is 111! ah well looks like ill have to do some fps experimenting the hard way.. Also I will have to rely on keeping a constant fps and NOT on changing the timestep for the type of game I am doing... It has to do with time travel so you can go back in time and visit a previous self but you cant cause a paradox with the physics! Thus changing the time step even by a small amount will cause a paradox :( its a paradoxical situation in itself :/

edit Minor Succes! Now I can have 80 boxes on screen. the only problem is as with all physics engines, it explodes because of the massive amount of weight on the bottom verlets. At least it runs at a steady 30-32 fps!

new control: press a to reset the min and max fps values for testing purposes. Please post your stats at the upper left hand side of the screen(only after pressing a of course!)

http://naillproductions.synthasite.com/resources/physicsenginetest%20(4).zip


slenkar(Posted 2009) [#12]
last time it was 6 but this time it was about 22


Xzider(Posted 2009) [#13]
noticed the slight lag at 20 - not bad physics


Sauer(Posted 2009) [#14]
Hey pretty cool stuff, I'm impressed.

I got very little lag, but I'm on an AlienWare here at school. Once I put about 40 physics blocks in, it started freaking out. The blocks were just flying everywhere. It made me smile.

Cool stuff though, where is this project headed?


Nate the Great(Posted 2009) [#15]
Cool stuff though, where is this project headed?



im not really sure where this project is headed. Maybe something similar to fantastic contraption or maybe even a game called ParadoxodaraP? anyway I am working on polygon collisions at the moment

I know the blocks expode but this wasnt meant for high stress and the time step is a bit high at the moment due to speed issues

Im glad its faster now! thanks for the feedback


Nate the Great(Posted 2009) [#16]
WOW! I feel extrememly stupid. I cant believe I didnt see it before. I just messed up when I was making one of my formulas (I like to make up my own because they get better every time) and it was leading to slow innacurate jittery physics! I fixed it and now I can have ~50 boxes before it starts to slow down and there are almost no jitters until it gets to ~90 boxes! now for the polygon collisions...

new download link!
http://naillproductions.synthasite.com/resources/physicsenginetest%20(4).zip

updated all links!


slenkar(Posted 2009) [#17]
you should put a box counter on the screen,

I got about 34 this time


Nate the Great(Posted 2009) [#18]
you should put a box counter on the screen


oops I planned to do that last time. will do for the next download

I got about 34 this time


wow thats a great improvement from 6! Im glad to know my optimizations did that much!


Nate the Great(Posted 2009) [#19]
ok I have some verlet-polygon collisons now! it should still be very fast! there is now a boxcounter for those of us too lazy to count how many times you hit the spacebar (myself included) please tell me how many boxes you can get without jitters or extended drops in frame rate. (note: I cut the time step in half thus doubleing the updates per loop so be on the lookout for strange behaviour)

download:
http://naillproductions.synthasite.com/resources/physicsenginetest%20(4).zip


Xzider(Posted 2009) [#20]
It was fine at 100-The physics went crazy at 111 (Guess they had nowhere else to go, started flying everywhere)-at 120 it started to slow down, and at 200 it was getting pretty laggy.


Nate the Great(Posted 2009) [#21]
ok wow that sounds great! 100 boxes? or 100 verlets? or 100 constraints?
I have only tested up to 90 boxes


slenkar(Posted 2009) [#22]
the FPS dropped to about 15 after 10-14 boxes


Nate the Great(Posted 2009) [#23]
thats odd it seems it has dropped significantly... I am working on optimizations and cleaning up messy bits of code at the moment. This has a long way to go. Thanks for testing Jeremy Paxman! just a wee little question: you dont happen to be running any programs like IE or word when testing this do you? When I open word my framerate also drops very low.


slenkar(Posted 2009) [#24]
oh yeah I will make sure I didnt have a youtube video in the background........
nope still 14 boxes, have you tried replacing lists with arrays?


Nate the Great(Posted 2009) [#25]
@ Jeremy Paxman - no I havent.. are they significantly faster?


slenkar(Posted 2009) [#26]
yep a lot faster i think,


Nate the Great(Posted 2009) [#27]
is there a specific method for using arrays instead of lists


slenkar(Posted 2009) [#28]
If you have some nested loops like:

working on a list with only 300 things in it

for p:physicsobject=eachin objlist
for q:physicsobject=eachin objlist

then its 90,000 operations so that might be slow


but anyway...

I think you just put your objects in an array,


Nate the Great(Posted 2009) [#29]
oh.. I see your point. I had never thought about that. So really it is phenomenal if any computer can get to say 75 boxes because thats 90,000 collision checks not counting the constraint loop. Also can you explain how I would go about using arrays? or maybe a link?


Ross C(Posted 2009) [#30]
Can't you do a quick distance check between 2 boxes?

If the widest part of the item+the widest part of the other item is less than the distance from centre to centre, then don't perform any more collision checks.


Nate the Great(Posted 2009) [#31]
@ ross C - I just did that :) its working quite well but not as quickly as I would like. It keeps track of the largest verlet and doubles that value. If the verlets are not within that distance of eachother on the x and y axises, it doesnt even bother checking anything else. overall I have gotten my box count to 60 on a dual core 2.4 ghz.

would it be more efficient and accurate enough to use a square root array to store all the sqareroots?


Xzider(Posted 2009) [#32]
@My earlier post, I meant boxes.

This little project reminds me of Garrys Mod...Think I'll go play it.


Sauer(Posted 2009) [#33]
Are you using bitwise operations of multiplication and division? You should see an increase in performance by using bit shifts, ands, and ors instead of multiplication, division (by powers of 2 that is) and mod.

Or does Blitz automatically convert division by base two numbers to bit shifts? I believe Python does this...


Nate the Great(Posted 2009) [#34]
@ sauer - you lost me at bitwise.. so are you saying I should divide by 1/ a number rather than multiply?


Sauer(Posted 2009) [#35]
No, you can use the commands SHR and SHL (bit shift right, bit shift left) which you can use in place of where you divide by a power of two.

If you've ever wondered why tile based games all have tiles that are a power of two (16,32,64 are common sizes) this is it. Division takes about 11 cpu instructions to complete, whereas a binary shift takes one. This can lead to great optimization.

Basically everywhere you would divide by a power of two, bit shift right, and whenever you want to multiply by a power of two, bit shift left. Basically all it does it takes all the bits and puts them one 'bin' to the right or left. I don't know how well your binary skills are but you can implement it without really knowing whats going on. Here are some examples:

x/32 = x>>5 ; we can shift x five bins right, dividing by 32 (2^5)
x/16 = x>>4 ; same thing, 16=2^4, so we just shift right four times
x/2 = x>>1 ; you can even bit shift when dividing by two

*note, >> would be SHR in blitz, in other languages it's actually an operator

You can do the same with multiplication, but instead of SHR use SHL.

I'm not sure how much MOD you are using, but if it's a lot and you are modding by a power of 2, there's a way to use bitwise OR to do that too, which I can also explain if needed.

Hopefully that made a bit of sense. <==EDIT Awesome unintentional pun by me. :)


Foppy(Posted 2009) [#36]
To avoid doing checks between all boxes you could divide the screens up into squares and keep track of a list of boxes for each square. Then for collision detection you only do checks between boxes in adjacent squares.


Nate the Great(Posted 2009) [#37]
@ foppy wouldnt that possibly be less efficient? I can see how that would work though. Ill give it a go

nice pun sauer but I soon found out that you cant do bitwise operations on floating point variables :( and that is the only place I need it

Here is my code for checking collisions between verlets just so you can see what I am getting at.. the boxes are made up of 4 verlets each.

For Local v:verlet = EachIn verletlist
For Local vv:verlet = EachIn verletlist
	Local dx# = v.x - vv.x
	Local dy# = v.y - vv.y
	If Abs(dx) < maxverlsiz And Abs(dy) < maxverlsiz Then
		If v.id <> vv.id   ' If Not the same verlet Or group
			
			Local dist# = Sqr ( dx#*dx# + dy#*dy#)		
			Local totalr# = v.siz# + vv.siz#
			If dist# < totalr# Then
				
				Local dmtr# = dist#-totalr#				
				Local Diffx# = ( dmtr# ) * ( dx# / dist# )
				Local Diffy# = ( dmtr# ) * ( dy# / dist# )
				If v.active = True Then
					v.x = v.x - Diffx# '* .5
					v.y = v.y - Diffy# '* .5
				EndIf
				
				If vv.active = True Then
					vv.x = vv.x + Diffx# '* .5
					vv.y = vv.y + Diffy# '* .5
				EndIf
				
			EndIf 				
		EndIf
	EndIf
Next
Next


Edit: I optimized this a lot with only a few lines of < and > statements!

Note: I took out the time step! It was an optimization but also because I am going for a different approach on verlet physics in which a time step messes everything up. I know its a radical move but its worth a shot. now I get 80 boxes until it starts lagging... my goal 150!


Foppy(Posted 2009) [#38]
wouldnt that possibly be less efficient?
Well, as the boxes move around there are extra operations to check if they go from one square into the next, and if so, a few operations to remove them from one list and add them to another.

However if there are a lot of objects I think the smaller amount of collision checks will outweigh the extra administration, because the number of potential collision checks increases quadratically while the administration costs increase linearly.

Maybe it's not as applicable to your physics engine as it is to my action games (or as easily applied). You would have to consider the size of those squares in relation to the maximum size of the objects: the algorithm relies on the fact that objects in non-adjacent square cannot touch each other.

You say you are already doing a quick distance check between the boxes, this means the relative profit from the above algorithm are smaller.

But still, perhaps an idea to keep in mind.


Nate the Great(Posted 2009) [#39]
But still, perhaps an idea to keep in mind.


ill definitely keep that in mind. it sounds like it could be just what I need but ill have to do some research and testing.


Damien Sturdy(Posted 2009) [#40]
I can fill the screen ith boxes now, I get 110 boxes before the simulation explodes.


dmaz(Posted 2009) [#41]
To avoid doing checks between all boxes you could divide the screens up into squares and keep track of a list of boxes for each square. Then for collision detection you only do checks between boxes in adjacent squares.

zoning... there are many different methods but they really do increase your collision efficiency.

[edit]below is the wrong solution![edit]
but for Nate's example above another type that you could be easily implemented is just making sure you never check a collision between the same 2 objects more than once. ie, once you check the first one with all the other ones, the first one shouldn't be in any more checks... etc.. every object only has to check the objects below it in the list because the objects above have already done this check. further more there is no reason to check the onbject against itself.


SuperStrict

Type mytype
	Global list:TList = New TList
	Global gi:Int = 0
	
	Field i:Int

	Method New()
		i = gi
		gi:+1
		list.AddLast Self
	End Method

End Type


For Local i:Int = 0 To 3
	New mytype
Next

For Local t:mytype = EachIn mytype.list
	For Local tt:mytype = EachIn mytype.list
		Print t.i+" checking "+tt.i
	Next
Next

'as opposed to...

Print "~nonly check once"
Local l:TLink = mytype.list.FirstLink()
While l <> mytype.list.LastLink()
	Local ll:TLink = l._succ
	While ll._succ <> mytype.list.FirstLink()
		Print mytype(l._value).i+" checking "+mytype(ll._value).i
		ll = ll._succ
	Wend
	l = l._succ
Wend
l = Null


now I would use a singly linked list so the loop would look like this
Local v:mytype = mytype.First()
While v
	Local vv = v.succ
	While vv
		Print v.i+" checking "+vv.i
		vv = vv.succ
	Wend
	v = v.succ
Wend



Nate the Great(Posted 2009) [#42]
@Dmaz - great Idea! thanks. I never really thought about that but it does seem like it would work :) ill give it a go


Nate the Great(Posted 2009) [#43]
thanks for all the help everyone (keep it coming) because I decided I will release this free with source code once I get it all fixed up.. keep in mind I made it for my own purposes so it may or maynot fulfill all of your requirements. and yes its superstrict :) I started it one day messing around to see if I could learn superstrict and types in bmax

if anyone has a list of features they want please post

so far there are

verlets!
constraints!
polygon segments (only to collide with ie. the polygons dont move they just sit there)
images attatched to constraints
gravity vector
a waterline with the following features
Global Waterlevel:Int = 400		'Waterlevel in pixels
Global Waterdensity:Float = 10		'The depth at wich boyancy maxes out
Global BoyancyForce:Float = .1		'Best if close to gravity
Global WaterFriction:Float = .01	'Needs to be really low for a very subtle effect


soon to come (note: these may take a while because I'm very sick right now)

optimization - a must
images attatched to verlets
verlets attatched to the constraints! I know.. its backwards!

readablitlity! - this is the last thing I will do. Its already readable but Ill try to make it as user friendly as possible


edit @ dmaz - your idea is one that seems good in theory but doesnt work in real life. I tried it and it actually does work a little but the system explodes with very few boxes. I think those extra iterations simply stabalize it more. stability comes first


dmaz(Posted 2009) [#44]

edit @ dmaz - your idea is one that seems good in theory but doesnt work in real life. I tried it and it actually does work a little but the system explodes with very few boxes. I think those extra iterations simply stabalize it more. stability comes first



well ya [hits self on head]. I wasn't thinking, in a physics sim you need to balance the collisions with all the other collisions in the local area because the collisions affect the result. I was thinking in terms of a shooter where you only care about the interaction between the 2 colliding onjects... as foppy said, zoning would be your best bet then since you limit your collisions to the local area (the box it's in and the surrounding boxes)


Nate the Great(Posted 2009) [#45]
well ya [hits self on head].


[hits self on head as well]
haha I guess it was worth a shot because now I will know not to try it again

edit ok I have properly applied friction!
it should also be almost twice as efficient as it used to be
notice the upper left segment of the triangle has a very high friction while the right side has almost no friction

please test here
http://naillproductions.synthasite.com/resources/NTG%20physics%20engine.zip


Nate the Great(Posted 2009) [#46]
ok updated!

now it is much more stable and the speed has doubled for me. I now get 130-140 boxes without any slowdown. :) it is also much more stable.

please test and post how many boxes you can get as well as your specs

link
http://naillproductions.synthasite.com/resources/NTG%20physics%20engine%20(2).zip


slenkar(Posted 2009) [#47]
how about the ability to 'move the camera' to allow for worlds bigger than the screen

I got 130 boxes this time!

Ever thought about adding joints?


Nate the Great(Posted 2009) [#48]
thanks for sticking with it Jeremy Paxman. I got 130 with the old demo that you just tried too but I just upped it to 170 with another rampage through the code optimizing even more. :) it is quite unstable though. I need to make it more stable now.

170 boxes = 680 verlets! and 1020 constraints! pretty good eh?

what do you mean by adding joints? I can make a ragdoll demo if you want me to for proof of concept of verlets and constraints. or do you mean something else?


slenkar(Posted 2009) [#49]
oh I didnt realise constraints were like joints,
a ragdoll demo would be fun!


Nate the Great(Posted 2009) [#50]
Ok I will put together an awesome ragdoll demo in a few days. hopefully tomorrow. but im really concerned as to how this is going to shape up as a full blown engine

edit by the way I got the camera stuff done, the demos just dont show it

edit - moved to here

http://www.blitzbasic.com/Community/posts.php?topic=83810