JV-ODE Physics Wrapper

Blitz3D Forums/Blitz3D Userlibs/JV-ODE Physics Wrapper

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Expanded Spheres Demo
Features: Autodisable, Applying forces to push and pull spheres with the mouse, Selecting bodies and creating joints between them, Applying forces to attract and repulse.

enjoy

; ###################################################################################################
; #									   JV-ODE - Spheres Demo										#
; #									Code by Jim Williams (VIP3R)									#
; ###################################################################################################

AppTitle "JV-ODE - Spheres Mouse Shot Demo"

Global snd1, piv1


Include "ode.bb"

Graphics3D 800,600,0,2
;Graphics3D 1024,768,0,2

Dim connect(256) ; joints
Dim Obj(1)
Dim Ent(1)

Type ODEGeom
	Field body
	Field geom
	Field mesh
End Type

; ###################################################################################################

;snd1=Load3DSound("Bounce.wav")
;piv1=CreatePivot()

; ### Setup ODE

Global World=dWorldCreate()
Global Space=dHashSpaceCreate(0)
Global ContactGroup=dJointGroupCreate(0)
Global p 

p=CreatePivot() ; Pivot at 0,0,0 ( supports Attract, and Explode )

s=0 ; New joint counter

dWorldSetGravity(World,0,-1,0)
dContactSetMode(dContactBounce + ContactSoftERP + dContactSoftCFM)
dContactSetMu(32)

; Autodisable bodies
dWorldSetAutoDisableFlag (World, 1)

; Increase to make bouncy
dContactSetBounce(0.3)

; Make contact surface soft
;dContactSetSoftERP(0.4)
;dContactSetSoftCFM(0.8)

smode=True

; ### Create light

;SetMousePtr()

ShowPointer

Global Light=CreateLight()

RotateEntity Light,45,-90,0
LightColor Light,255,255,255
AmbientLight 130,130,130

; ### Create camera

Global Camera=CreateCamera()
CameraClsColor Camera,0,0,0
CameraRange Camera,1,1000

;Correct camera distortion
CameraZoom camera, 1.5

;mic1=CreateListener(camera) ; Create listener, make it child of camera 

PositionEntity Camera,0,20,-50
RotateEntity Camera,30,0,0

; ### Create plane

dCreatePlane(Space,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

Mirror=CreateMirror()

; ###################################################################################################

While Not KeyHit(1)

	PTime=MilliSecs()
	
	
	
	dSpaceCollide(Space,World,ContactGroup)
	
	updatefriction
		
	dWorldQuickStep(World,0.15)
		
	dJointGroupEmpty(ContactGroup)
		
	
		
	If MilliSecs()-Timer>700
		balls=balls+1
		If balls<10 Then
				AddObject()
		End If
		Timer=MilliSecs()
	End If

	UpdateGeoms()

	PhysicsTime#=MilliSecs()-PTime

	UpdateWorld

	RenderWorld

	Text 0,0,"JV-ODE Version "+dGetVersion()
	Text 0,15,"Physics Time:"+PhysicsTime
	Text 0,30,"A:Attract, E:Explode, M: Mode Select"
	
	; M - Selects Mode
	If KeyHit(50)>0 Then
		smode=Not smode
	End If
	
	Select smode
	
		Case True
			Text 0,45,"Mode: Move bodies "
			Text 0,60,"LM:Push, RM:Pull "
	
		Case False
			Text 0,45,"Mode: Select bodies "
			Text 0,60,"LM:SetBallJoint, RM:Select Body"
			Text 0,75,obj(0)
			Text 0,90,obj(1)
	End Select
		
	
	
	Flip
	

Select smode

	Case True
		; Push on the ball based on the entitypicked vector
		If MouseDown(1) Then 
		
			CameraPick(camera, MouseX(), MouseY())
			
			If PickedEntity()<>0 Then
				EntityColor PickedEntity(),0,255,0
				For ode.ODEGeom=Each ODEGeom
					If ode\mesh=PickedEntity()
						dBodyEnable(ode\body) 
						k=-10
						dBodyAddForce ode\body,k*PickedNX#(),k*PickedNY#(),k*PickedNZ#()
						
						Exit
					End If
				Next
			End If
		End If
		
		; Pull on the ball based on the entitypicked vector
		If MouseDown(2) Then 
		
			CameraPick(camera, MouseX(), MouseY())
			
			If PickedEntity()<>0 Then
				EntityColor PickedEntity(),0,255,0
				For ode.ODEGeom=Each ODEGeom
					If ode\mesh=PickedEntity()
						dBodyEnable(ode\body) 
						k=10
						dBodyAddForce ode\body,k*PickedNX#(),k*PickedNY#(),k*PickedNZ#()
						
						Exit
					End If
				Next
			End If
		End If
		
	Case False
			
		If MouseHit(2) Then 
	
			CameraPick(camera, MouseX(), MouseY())
			
			If PickedEntity()<>0 Then
				EntityColor PickedEntity(),0,0,255
				For ode.ODEGeom=Each ODEGeom
					If ode\mesh=PickedEntity()
						ix=Not ix
						obj(ix)=ode\body
						ent(ix)=ode\mesh
						PositionEntity 	p,EntityX(ode\mesh),EntityY(ode\mesh),EntityZ(ode\mesh)
						Exit
					End If
				Next
			End If
		End If
		
		If MouseHit(1) And obj(0)>0 And obj(1)>0 Then 
			s=s+1
			connect(s)=dJointCreateBall (world,0)
			dJointAttach(connect(s),obj(0),obj(1))
			dJointSetBallAnchor(connect(s),dBodyGetPositionX(obj(0)),dBodyGetPositionY(obj(0)),dBodyGetPositionZ(obj(0)))
			dBodyEnable(obj(0))
			dBodyEnable(obj(1))
		End If
		
	
End Select

;(A)ttract 
If KeyDown(30) Then 
	For ode.ODEGeom=Each ODEGeom
		;Calc vector from ball to pivot
		PointEntity ode\mesh,p
		TFormVector 0,0,1,ode\mesh,0
		dBodyEnable(ode\body)
		k=10
		dBodyAddForce ode\body,k*TFormedX#(),k*TFormedY#(),k*TFormedZ#()
		
	Next
End If

;(E)xplode
If KeyDown(18) Then 
	For ode.ODEGeom=Each ODEGeom
		;Calc vector from ball to pivot
		PointEntity ode\mesh,p
		TFormVector 0,0,1,ode\mesh,0
		dBodyEnable(ode\body) 
		k=-10
		dBodyAddForce ode\body,k*TFormedX#(),k*TFormedY#(),k*TFormedZ#()
		
	Next
End If

Wend

dJointGroupDestroy(ContactGroup)
dSpaceDestroy(Space)
dWorldDestroy(World)
dCloseODE()

End

; ###################################################################################################

Function AddObject()

xp=Rand(-8,8)
zp=Rand(-8,8)
ode.ODEGeom=New ODEGeom
ode\body=dBodyCreate(World)
dBodySetRotation(ode\body,0,0,0)
dBodySetPosition(ode\body,xp,30,zp)
ode\geom=dCreateSphere(Space,3)
dGeomSetBody(ode\geom,ode\body)
ode\mesh=CreateSphere()
ScaleMesh ode\mesh,3,3,3
EntityColor ode\mesh,Rand(255),Rand(255),Rand(255)
EntityAlpha ode\mesh,1
EntityShininess ode\mesh,0.7

;Set Autodisable parms to your liking
	dBodySetAutoDisableFlag(ode\body,1)
	dBodySetAutoDisableAngularThreshold(ode\body,.05)
	dBodySetAutoDisableLinearThreshold(ode\body,.05)
	dBodySetAutoDisableSteps (ode\body, 1)

;Allow sphere to be picked
EntityPickMode ode\mesh,2

End Function

; ###################################################################################################

Function UpdateGeoms()

For ode.ODEGeom=Each ODEGeom
If dBodyIsEnabled(ode\body)
	RotateEntity ode\mesh,dGeomGetPitch#(ode\geom),dGeomGetYaw#(ode\geom),dGeomGetRoll#(ode\geom)
	PositionEntity ode\mesh,dGeomGetPositionX#(ode\geom),dGeomGetPositionY#(ode\geom),dGeomGetPositionZ#(ode\geom)
	EntityColor ode\mesh,0,255,0
Else
	EntityColor ode\mesh,255,0,0
End If
Next

End Function

; ###################################################################################################

Function AngularDamp(body,damp#)
  dBodyAddTorque body,dBodyGetAngularVelX(body)*-damp,dBodyGetAngularVelY(body)*-damp,dBodyGetAngularVelZ(body)*-damp
End Function

; ###################################################################################################

Function LinearDamp(body,damp#)
  dBodyAddForce body,dBodyGetLinearVelX(body)*-damp,dBodyGetLinearVelY(body)*-damp,dBodyGetLinearVelZ(body)*-damp
End Function

; ###################################################################################################

Function UpdateFriction()

For ode.ODEGeom=Each ODEGeom
	If dBodyIsEnabled(ode\body)
		numjoints=dBodyGetNumJoints(ode\body)
		If numjoints>0 
		
			For joints=0 To numjoints-1
				joint=dBodyGetJoint(ode\body,joints)
				If dJointGetType(joint)=dJointTypeContact
					
					; Get linear velocity vector
			  		ax#=dBodyGetLinearVelX#(ode\body)
			  		ay#=dBodyGetLinearVelY#(ode\body)
				    az#=dBodyGetLinearVelZ#(ode\body)
					; Get Angular velocity vector
			  		bx#=dBodyGetAngularVelX#(ode\body)
			  		by#=dBodyGetAngularVelY#(ode\body)
					bz#=dBodyGetAngularVelZ#(ode\body)
			  		; Calculate magnitudes
					ForceA#=Sqr(ax*ax+ay*ay+az*az)
					ForceB#=Sqr(bx*bx+by*by+bz*bz)
					
					
					If ForceA>.01
						LinearDamp(ode\body,.07)
					End If
					
	
					If ForceB>.01
						AngularDamp(ode\body,.07)
					End If
					
				End If
			Next
		End If
	End If
Next

End Function

Function SetMousePtr()
MousePtr = LoadImage("c:\pointer.bmp")
MaskImage MousePtr,0,0,0
End Function