Do you have to do it yourself or is there some library I can use?
Well, there were some physics wrappers written for Minib3d but the more complete ones were either restricted, like the demo for Itmbin's brightrealm wrapper or Windows only like JV-ODE physics. There are a few free Newton wrappers around but I haven't really looked into it, as physics is kind of last on my todo list. For a ready-to-use cross-platform physics solution I believe AGK2 is what many folks are using.
OpenB3D features also some physics features itself, since it allows to use constraints, and to bind an entity to some constrained pivots, to simulate a rigid body
Hi Angelo,
nice to see you back at SyntaxBomb. Did you ever write a demo of how to correctly set up constraints? I couldn't figure out how to use them.
Here is an old quick and dirty example:
#include "openb3d.bi"
screen 18, 32, , &h10002
Graphics3d 640,480,32,1,1
var camera=createcamera(0)
var cube=createcube()
dim piv(8) as any ptr
for i as integer=1 to 8
piv(i)=createpivot()
entitytype piv(i),1
entityradius piv(i),.01
next
positionentity piv(1),-1,-1,-1
positionentity piv(2), 1,-1,-1
positionentity piv(3),-1, 1,-1
positionentity piv(4), 1, 1,-1
positionentity piv(5),-1,-1, 1
positionentity piv(6), 1,-1, 1
positionentity piv(7),-1, 1, 1
positionentity piv(8), 1, 1, 1
for i as integer=1 to 8
actvector piv(i),0,-.01,0
actnewtonian piv(i),.9
for i2 as integer=i+1 to 8
createconstraint piv(i),piv(i2), entitydistance(piv(i),piv(i2))
next
next
createrigidbody cube,piv(1),piv(2),piv(3),piv(5)
fitmesh cube,0,0,0,1,1,1
var cube2=createcube()
dim piv2(8) as any ptr
for i as integer=1 to 8
piv2(i)=createpivot()
entitytype piv2(i),1
entityradius piv2(i),.01
next
positionentity piv2(1), 2,-1,-1
positionentity piv2(2), 4,-1,-1
positionentity piv2(3), 2, 1,-1
positionentity piv2(4), 4, 1,-1
positionentity piv2(5), 2,-1, 1
positionentity piv2(6), 4,-1, 1
positionentity piv2(7), 2, 1, 1
positionentity piv2(8), 4, 1, 1
for i as integer=1 to 8
actvector piv2(i),0,-.01,0
actnewtonian piv2(i),.9
for i2 as integer=i+1 to 8
createconstraint piv2(i),piv2(i2), entitydistance(piv2(i),piv2(i2))
next
next
createrigidbody cube2,piv2(1),piv2(2),piv2(3),piv2(5)
fitmesh cube2,0,0,0,1,1,1
updateworld
renderworld
entitytype cube,-2
entitytype cube2,-2
var plane=createplane()':scaleentity plane, 100,.1,100
entitytype plane,-2
moveentity plane,0,-4,15
entitycolor plane,255,0,0
collisions 1,2,1,3
var light=createlight()
positionentity light,5,5,5
pointentity light,cube
moveentity camera,0,2,-15
pointentity camera,cube
var s=createcube
positionentity s,3,-3,0
scaleentity s,2,1,2
entitytype s,-2
'turnentity plane,0,0,10
dim key as string
do
key=inkey
if key=chr(255)+"H" then moveentity s,0,0,.1
if key=chr(255)+"P" then moveentity s,0,0,-.1
if key=chr(255)+"M" then moveentity s,.1,0,0
if key=chr(255)+"K" then moveentity s,-.1,0,0
updateworld 1
renderworld
sleep 1
flip
flip
loop until key=chr(27)
Hi Angelo,
sorry for not replying to this in time, the example is quite impressive, but the boxes keep moving long after they should have stopped, so is there a way around this? Like a minimum friction or gravity thing.
Thanks.
In the line "actnewtonian piv(i),.9", try changing the ".9" to lower values, to simulate friction.
True friction against surfaces is not implemented, at the moment, that command simulates a generic "air friction". By the way, it could be possible to simulate a more compex friction, for example by checking if the entity is colliding with something and changing its action
Yes, that works, thanks. If the action values are set right it looks realistic. Hey, that's pretty cool using actions with constraints. But why does ActNewtonian need a smaller value to increase friction? I think it would be worth adding true friction based on collisions, a dynamic value would increase realism, maybe an entity weight would help.
It needs a smaller value because momentum is managed by measuring how much a entity has moved in the last step, and then moving it again along the same vector, by the previous amount of movement multiplied by a coefficient. A coefficient of 1 means perfect Newtonian momentum with no friction. A coefficient of 0 means no momentum. And so on.
A dynamic system would surely increase realism, but would make the library more complex (making it much slower) and less easy to learn. The reason I loved original Blitz3D is that it was simple and immediate, you could do almos everything with a single instruction. I tried to keep the same approach in new features
I see, thanks for the explanation.
After some tests I find the problem was setting cube EntityType to 2, which was the same as the ground and caused the jittering, so you can use a newtonian value of .9. I agree there's no real need to make the library more complex for this, and it looks like users could just write collision-based friction outside the library.
Another problem, I notice the cubes half sink into the larger cube as they roll off it, I don't suppose there's a way to increase the precision of this type of collision? I tried adding constraints at halfway points, and adding constraints to the larger cube, but it didn't work.
To increase the precision you can add more halfway points (so far, there are eight halfway points, at the vertexes of the cube, but you can add more: one at the center of each face, for example). Then you must add constraints between them and the other ones, of course. The more points you add (and check for collisions) the more accurate collision will be (of course, you will increase the amount of calculations needed)
Thanks. I added more constraints along each edge of the cube which is 12 and it worked, but I had to be careful adding constraints, just attaching all constraints to eachother caused a collapse, so primary constraints were attached first, then secondary constraints to both primary and secondary. It's not very noticeable and the cube still sinks into the base cube a little, but it is more realistic. Here's the example for Freebasic:
#include "openb3d.bi"
screen 18, 32, , &h10002
Graphics3d 640,480,32,0,2
var camera=createcamera(0)
var cube=createcube()
entitycolor cube,255,255,0
dim piv(20) as any ptr
for i as integer=1 to 20
piv(i)=createpivot()
entitytype piv(i),1
entityradius piv(i),.01
next
positionentity piv(1),-1,-1,-1
positionentity piv(2), 1,-1,-1
positionentity piv(3),-1, 1,-1
positionentity piv(4), 1, 1,-1
positionentity piv(5),-1,-1, 1
positionentity piv(6), 1,-1, 1
positionentity piv(7),-1, 1, 1
positionentity piv(8), 1, 1, 1
positionentity piv(9),-1,-1, 0
positionentity piv(10), 0,-1, 1
positionentity piv(11), 0,-1, 1
positionentity piv(12), 1,-1, 0
positionentity piv(13),-1, 1, 0
positionentity piv(14), 0, 1, 1
positionentity piv(15), 0, 1, 1
positionentity piv(16), 1, 1, 0
positionentity piv(17),-1, 0,-1
positionentity piv(18), 1, 0, 1
positionentity piv(19),-1, 0, 1
positionentity piv(20), 1, 0,-1
for i as integer=1 to 8
actvector piv(i),0,-.01,0
actnewtonian piv(i),.9
for i2 as integer=i to 8
if i<>i2 then
createconstraint piv(i),piv(i2), entitydistance(piv(i),piv(i2))
endif
next
next
for i as integer=9 to 20
actvector piv(i),0,-.01,0
actnewtonian piv(i),.9
for i2 as integer=1 to 20
if i<>i2 then
createconstraint piv(i),piv(i2), entitydistance(piv(i),piv(i2))
endif
next
next
createrigidbody cube,piv(1),piv(2),piv(3),piv(5)
fitmesh cube,0,0,0,1,1,1
var cube2=createcube()
dim piv2(8) as any ptr
for i as integer=1 to 8
piv2(i)=createpivot()
entitytype piv2(i),1
entityradius piv2(i),.01
next
positionentity piv2(1), 2,-1,-1
positionentity piv2(2), 4,-1,-1
positionentity piv2(3), 2, 1,-1
positionentity piv2(4), 4, 1,-1
positionentity piv2(5), 2,-1, 1
positionentity piv2(6), 4,-1, 1
positionentity piv2(7), 2, 1, 1
positionentity piv2(8), 4, 1, 1
for i as integer=1 to 8
actvector piv2(i),0,-.01,0
actnewtonian piv2(i),.9
for i2 as integer=i+1 to 8
createconstraint piv2(i),piv2(i2), entitydistance(piv2(i),piv2(i2))
next
next
createrigidbody cube2,piv2(1),piv2(2),piv2(3),piv2(5)
fitmesh cube2,0,0,0,1,1,1
updateworld
renderworld
'entitytype cube,-2
'entitytype cube2,-2
var plane=createplane()':scaleentity plane, 100,.1,100
entitytype plane,-2
moveentity plane,0,-4,15
entitycolor plane,255,0,0
var light=createlight()
positionentity light,5,5,5
pointentity light,cube
moveentity camera,0,2,-15
pointentity camera,cube
var s=createcube
positionentity s,2,-3,0
scaleentity s,2,1,2
entitytype s,-2
'turnentity plane,0,0,10
collisions 1,2,1,3
dim key as string
do
key=inkey
if key=chr(255)+"H" then moveentity s,0,0,.1
if key=chr(255)+"P" then moveentity s,0,0,-.1
if key=chr(255)+"M" then moveentity s,.1,0,0
if key=chr(255)+"K" then moveentity s,-.1,0,0
updateworld 1
renderworld
sleep 1
flip
loop until key=chr(27)