Here's an example program for magnetism for people (Wayne!) to have a nose at.
Hit <spcae> to turn on the magnet. Cursor keys let you change view. When an object hits the magnet it's deactivated (geom set to no body) and turned blue.
This example is all blocks. From line 92 where the objects are created you can select between all blocks, spheres, or a mixture. With blocks and spheres they hit but penetrate a little into the surface. Line 113 has an option to double the size of the blocks. When big they hit the magnet but don't get deactivate, but also don't penetrate.
Probems to solve are to stop any objhect penetration, and to ensure all objects stick regardless of size.
An extra feature wouldn't shouldn't be too hard is to have objects get deactivated when they hit any magnetised object.
The ultimate feature would be to have objects slide around other magnetised objects towards the centre of magnetism.
Also in the code, but disabled above, is code to limit the object's linear velocity. When using powerful magnets over large distances the acceleration becomes extreme and the objects can just fly through the magnet. In real life wind resistance limits top speed and reduces acceleration as the object gets faster. Not sure how to emulate this is ODE. I'm not after a full air dynamic model, but to limit top speed . In the above example I've capped the maximum force applied by the magnet which seem fairly realistic in results.
Include "JV-ODE.bb" Graphics3D 800,600,0,2 Global WorldERP#=0.8 ; ### World Error Correction Global WorldFriction#=0 ; ### World Friction Global SpaceInfo=0 Global Pointer Global PlaneGeom Global magnet.ODEGeom, magnet_on Const NUM_OBJECTS=20 Type ODEGeom Field body Field geom Field mesh End Type Dim clutter.ODEGeom(NUM_OBJECTS) ; ################################################################################################### ; ### Setup ODE Global World=dWorldCreate() Global Space=dHashSpaceCreate(0) Global GroundSpace=dHashSpaceCreate(Space) Global ObjSpace=dHashSpaceCreate(Space) Global ContactGroup=dJointGroupCreate(0) dWorldSetAutoDisableFlag(World,1) dWorldSetGravity(World,0,-0.98,0) dWorldSetERP(World,WorldERP) dContactSetMode(dContactSlip1) dContactSetMu(WorldFriction) ; ### Create light Light=CreateLight() RotateEntity Light,45,-90,0 LightColor Light,255,255,255 AmbientLight 130,130,130 ; ### Create camera pivot=CreatePivot() Camera=CreateCamera(pivot) PositionEntity Camera,-0,40,-80 RotateEntity Camera,30,0,0 CameraClsColor Camera,0,0,0 CameraRange Camera,1,1000 CameraZoom camera,2 ; ### Create plane PlaneGeom=dCreatePlane(GroundSpace,0,1,0,0) Plane=CreatePlane() EntityAlpha Plane,0.8 PlaneTexture=CreateTexture(128,128,9) ClsColor 0,200,80 Cls Color 255,255,255 Rect 0,0,64,64,1 Rect 64,64,64,64,1 CopyRect 0,0,128,128,0,0,BackBuffer(),TextureBuffer(PlaneTexture) ScaleTexture PlaneTexture,20,20 EntityTexture Plane,PlaneTexture,0,0 ; ### Create some objects GRAVITY_ENABLED=True SIZE#=2.0 CYLINDER_RADIUS#=1.7319 DENSITY#=1.0 FRICTION#=10.0 gamma#=0.5 ; Change Cube size to match Sphere's volume SIZE=3 ; Ode3 = Cube with density based mass x#=1.0 y#=5.0 z#=1.0 magnet.ODEGeom=New ODEGeom magnet\geom=dCreateBox(Space,x,y,z) dGeomSetPosition (magnet\geom,0,2.5,0) dGeomContactSetMu(magnet\geom,0.0) magnet\mesh=CreateCube() ScaleMesh magnet\mesh,x/2,y/2,z/2 PositionEntity magnet\mesh,0,2.5,0 EntityColor magnet\mesh,255,0,0 SeedRnd MilliSecs() For n=1 To NUM_OBJECTS clutter(n)=New ODEGeom ; r=Rand(1,2) ; Random objects ; r = 1 ; Create all objects as spheres r = 2 ; Create all objects as boxes x#=Rnd(1,3) y#=Rnd(1,3) z#=Rnd(1,3) Select r Case 1 clutter(n)\body=dBodyCreate(World) clutter(n)\geom=dCreateSphere(Space,x) dGeomSetBody(clutter(n)\geom,clutter(n)\body) dGeomContactSetMu(clutter(n)\geom,0.0) mass=dMassCreate() dMassSetSphere(mass,DENSITY,x) dBodySetMass(clutter(n)\body,mass) dMassDestroy(mass) clutter(n)\mesh=CreateSphere() ScaleMesh clutter(n)\mesh,x,x,x Case 2 ; x=x*2 : y=y*2 : z=z*2 ; Double box sizes clutter(n)\body=dBodyCreate(World) clutter(n)\geom=dCreateBox(Space,x,y,z) dGeomSetBody(clutter(n)\geom,clutter(n)\body) dGeomContactSetMu(clutter(n)\geom,0.0) mass=dMassCreate() dMassSetBox(mass,DENSITY,x,y,z) dBodySetMass(clutter(n)\body,mass) dMassDestroy(mass) clutter(n)\mesh=CreateCube() ScaleMesh clutter(n)\mesh,x/2,y/2,z/2 End Select dBodySetRotation(clutter(n)\body,Rand(-90,90),Rand(-90,90),Rand(-90,90)) dBodySetPosition(clutter(n)\body,Rand(-20,20),Rand(3,5),Rand(-20,20)) Next time=0 magnet_on=False While Not KeyHit(1) time=advance_simulation(time) If KeyHit(57) magnet_on=True ElseIf KeyDown(203) TurnEntity pivot,0,0.5,0 ElseIf KeyDown(205) TurnEntity pivot,0,-0.5,0 ElseIf KeyDown(200) MoveEntity camera,0,0,1 ElseIf KeyDown(208) MoveEntity camera,0,0,-1 EndIf PointEntity camera,magnet\mesh UpdateWorld RenderWorld y=15 Text 20,y,OBJECT_MASS : y=y+15 Flip Wend dJointGroupDestroy(ContactGroup) dSpaceDestroy(Space) dWorldDestroy(World) dCloseODE() End Function advance_simulation(t%) ; Advances the simluation, incrementing frame count dSpaceCollide(Space,World,ContactGroup) ;#Region Apply Forces objects_stopped=True ;#End Region For n=1 To NUM_OBJECTS PositionEntity clutter(n)\mesh,dGeomGetPositionX(clutter(n)\geom),dGeomGetPositionY(clutter(n)\geom),dGeomGetPositionZ(clutter(n)\geom) RotateEntity clutter(n)\mesh,dGeomGetPitch(clutter(n)\geom),dGeomGetYaw(clutter(n)\geom),dGeomGetRoll(clutter(n)\geom) If magnet_on apply_magnetism(magnet,clutter(n)) EndIf ; Per collision processing If dBodyIsEnabled(clutter(n)\body) numCollisions=dGeomCountCollisions(clutter(n)\geom) If numCollisions>0 ; For each collision, test if with magnet For m=1 To numCollisions collision_geom=dGeomCollisionGeom(clutter(n)\geom,m) If collision_geom=magnet\geom ; Collided with magnet dGeomSetBody(clutter(n)\geom,0) EntityColor clutter(n)\mesh,0,0,255 EndIf Next EndIf ; Limit Linear Velocity... ; bx#=dBodyGetLinearVelX(clutter(n)\body) ; by#=dBodyGetLinearVelY(clutter(n)\body) ; bz#=dBodyGetLinearVelZ(clutter(n)\body) ; b#=Sqr((bx*bx)+(by*by)+(bz*bz)) ; If b>MAX_SPEED ; b=MAX_SPEED/b ; dBodySetLinearVel(temp\body,bx*b,by*b,bz*b) ; EndIf EndIf Next dWorldQuickStep(World,0.15) dJointGroupEmpty(ContactGroup) Return t+1 End Function Function apply_magnetism(magnet.ODEGeom, target.ODEGeom) ; FUNCTION : Applies a force in direction of fan based on angle to fan dBodyGetPosition(target\body) x#=dVectorX() y#=dVectorY() z#=dVectorZ() dGeomGetPosition(magnet\geom) x#=x-dVectorX() y#=y-dVectorY() z#=z-dVectorZ() ; (x,y,z) is direction of force. Need angle and magnitude mag#=Sqr(x * x + y * y + z * z) magnitude#=mag If mag>0 x = x / mag y = y / mag z = z / mag Else x=1.0 y=0.0 z=0.0 EndIf magnitude=magnitude*magnitude ; (x,y,z) = normalized vector magnitude#=1.0/(magnitude) If magnitude > 0.001 magnitude=magnitude*1000.0 x=x * magnitude# y=y * magnitude# z=z * magnitude# If magnitude>500 magnitude=500 dBodyEnable(target\body) dBodyAddForce (target\body,-x,-y,-z) Else If magnitude>0.01 dBodyEnable(target\body) dBodyAddForce (target\body,-x,-y,-z) EndIf EndIf End Function
Hit <spcae> to turn on the magnet. Cursor keys let you change view. When an object hits the magnet it's deactivated (geom set to no body) and turned blue.
This example is all blocks. From line 92 where the objects are created you can select between all blocks, spheres, or a mixture. With blocks and spheres they hit but penetrate a little into the surface. Line 113 has an option to double the size of the blocks. When big they hit the magnet but don't get deactivate, but also don't penetrate.
Probems to solve are to stop any objhect penetration, and to ensure all objects stick regardless of size.
An extra feature wouldn't shouldn't be too hard is to have objects get deactivated when they hit any magnetised object.
The ultimate feature would be to have objects slide around other magnetised objects towards the centre of magnetism.
Also in the code, but disabled above, is code to limit the object's linear velocity. When using powerful magnets over large distances the acceleration becomes extreme and the objects can just fly through the magnet. In real life wind resistance limits top speed and reduces acceleration as the object gets faster. Not sure how to emulate this is ODE. I'm not after a full air dynamic model, but to limit top speed . In the above example I've capped the maximum force applied by the magnet which seem fairly realistic in results.