JV-ODE: Break my tables!

Blitz3D Forums/Blitz3D Userlibs/JV-ODE: Break my tables!

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.

Hi All,

Just beginning with ODE and here a experiment with breakable tables (yes, based on code you guys did before, so nothing new). I'm curious to know if you guys know any other ways to 'get bodies to relax' and auto disable themselves.

In the demo you can see when you've got lots of objects stacked on top of each other they keep bouncing around amongst each other. Lowering angular&linear thresholds can only go so far untill bodies come to rest in an unrealistic pose...

cheers,
Danny
p.s. How do you post a small box with code in it? unlike this big chunk:
Include "JV-ODE.bb"

; DANNY's Broken Table Test

Const ANGTHRESH# = 0.1		;default auto disable angular threshold
Const LINTHRESH# = 0.1		;default auto disable linear threshold
Const STEPTHRESH = 1

Graphics3D 800,600,0,2

Type odeGeom
	Field body
	Field geom
	Field mesh
	Field lastForce#
End Type

; ###################################################################################################
; ### Setup ODE

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

dWorldSetGravity(World,0,-0.48,0)
dWorldSetERP World, 0.25

dContactSetMu(40)

SeedRnd 666

Global camera, camerapivot
Create3D()

;add some random tables
r#=1
addTable -3,2,3, 2,1,2
addTable  3,2,3, 2,1,2
addTable -3,2,-3, 2,1,2
addTable  3,2,-3, 2,1,2
addTable  0,3,0, 2,1,2

; ###################################################################################################
;sfx = Load3DSound("bin\woodimpact02.wav")
;Global break = Load3DSound("bin\Door.wav")
;CreateListener camera

goSim = False

fps = 0
frames = 0
ftime = MilliSecs()+1000

While Not KeyHit(1)

	;make dizzy
	TurnEntity camerapivot, 0, 0.1, 0

	;ENTER = more boxes
	If KeyDown(28) Then AddObject(Rand(-r,r),Rand(-r,r))

	;SPACE = more tables
	If KeyHit(57) Then AddTable(Rand(-r,r),Rand(3,6),Rand(-r,r),2,1,2)

	If goSim Then	
		;add random boxes every couple ms
		If MilliSecs()-BoxTimer>50
			numbox=numbox+1
			;limit amount of boxes
			If numbox < 50 Then
				r# =4
				AddObject(Rand(-r,r),Rand(-r,r))
			EndIf
			BoxTimer=MilliSecs()
		End If

		;-
		PTime=MilliSecs()
		dSpaceCollide(Space,World,ContactGroup)
		dWorldQuickStep(World,0.1)
		dJointGroupEmpty(ContactGroup)	
		PhysicsTime#=MilliSecs()-PTime

		;check for breakage
		JointLimits(1.5)

	EndIf

	UpdateGeoms()

	UpdateWorld
	RenderWorld

	;fps check
	If MilliSecs() >=ftime Then
		goSim = True ;delay simulation with a second
		fps=frames
		frames=0
		ftime=MilliSecs()+999
	Else
		frames=frames+1
	EndIf

	;debug
	Color 250,250,250
	Text 5,0,"JV-ODE Version "+dGetVersion()
	Text 5,15,"Physics Time:"+PhysicsTime
	Text 5,30,"FPS: "+FPS
	Text GraphicsWidth()/2,50,"GREEN objects are ENABLED/ACTIVE - RED objects are DISABLED", 1
	Text GraphicsWidth()/2,65,"Press ENTER for more boxes", 1
	Text GraphicsWidth()/2,80,"Press SPACEBAR to add a Breakable Table!", 1

	;show
	Flip 1

Wend

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

End

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

Function Create3D()

;| Default 3d scene

	; ### Create light
	
	Light=CreateLight()
	
	RotateEntity Light,45,-90,0
	LightColor Light,255,255,255
	AmbientLight 130,130,130
	
	; ### Create camera
	camerapivot = CreatePivot()
	Camera=CreateCamera(camerapivot)
	CameraClsColor Camera,0,0,0
	CameraRange Camera,0.01,250
	PositionEntity Camera,-5,7,-7
	PositionEntity camerapivot, 0,1,0
	PointEntity camera, camerapivot
	;make top text readable
	CameraFogColor camera, 0,0,0
	CameraFogRange camera, 5,30
	CameraFogMode camera, 1

	; ### Create plane
	dCreatePlane(Space,0,1,0,0)
	Plane=CreatePlane()
	EntityAlpha Plane,0.95
	PlaneTexture=CreateTexture(128,128,9)
	ClsColor 220,210,200
	Cls
	Color 150,120,110
	Rect 0,0,64,64,1
	Rect 64,64,64,64,1
	CopyRect 0,0,128,128,0,0,BackBuffer(),TextureBuffer(PlaneTexture)
	ScaleTexture PlaneTexture,5,5
	EntityTexture Plane,PlaneTexture,0,0
	Mirror=CreateMirror()
	Color 255,255,255

End Function

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

Function AddObject(xp#=666,zp#=666)

	size# = Rnd#(0.25,0.65)
	range# = 0.5

	If xp=666 Then xp=Rand(-range#,range#)
	yp=Rand(7,15)
	If zp=666 Then zp=Rand(-range#,range#)

	ode.ODEGeom=New ODEGeom

	ode\body=dBodyCreate(World)
	dBodySetRotation(ode\body,0,0,0)
	dBodySetPosition(ode\body,xp,yp,zp)
	dBodySetAutoDisableFlag(ode\body,1)

	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(Space,size#,size#,size#)
	dGeomSetBody(ode\geom,ode\body)

	ode\mesh=CreateCube()
	ScaleMesh ode\mesh,size#/2,size#/2,size#/2
	EntityColor ode\mesh,Rand(255),Rand(255),Rand(255)
	EntityAlpha ode\mesh,1
	EntityShininess ode\mesh,0.7

	mass = dMassCreate()
	dMassSetBoxTotal mass, 25.0, size#,size#,size#
	dBodySetMass ode\body, mass
	dMassDestroy mass

End Function

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

Function AddTable(xp#, yp#, zp#, w#,h#,d#)

;# Creates a table with 4 legs - breakable legs! :)

	w# = Rnd(w#*0.5,w#*1.5)		;add some variation to the table's dimensions
	h# = Rnd(h#*0.5,h#*1.5)
	d# = Rnd(d#*0.5,d#*1.5)

	;table top dimensions
	th# = h# * 0.1

	;leg dimensions
	lw# = w#*0.1
	lh# = h#*0.9
	ld# = d#*0.1

	;create tabletop
	ode.odegeom = New odegeom
	ode\body = dBodyCreate(world)
	dBodySetPosition ode\body, xp#, yp#, zp#
	dBodySetRotation ode\body, 0,0,0
	dBodySetAutoDisableFlag ode\body, 1
	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(space,w#,th#,d#)
	dGeomSetBody ode\geom, ode\body	

	ode\mesh=CreateCube()
	EntityColor ode\mesh, 100,50,0
	ScaleMesh ode\mesh, w#/2,th#/2,d#/2
	tableBody = ode\body

;	yp# = yp# - 0.01 ;-> create small gap between table top & legs

	;create leg 1
	ode.odegeom = New odegeom
	ode\body = dBodyCreate(world)
	dBodySetPosition ode\body, xp#-w#/2+lw#/2, yp#-lh#/2-th#/2, zp#-d#/2+ld#/2
	dBodySetRotation ode\body, 0,0,0
	dBodySetAutoDisableFlag ode\body, 1
	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(space,lw#,lh#,ld#)
	dGeomSetBody ode\geom, ode\body	

	ode\mesh=CreateCube()
	EntityColor ode\mesh, 200,100,0
	ScaleMesh ode\mesh, lw#/2,lh#/2,ld#/2

	;join the legs to the table
	joint = dJointCreateHinge(world,0)
	dJointAttach joint, tableBody, ode\body
	dJointSetHingeAxis joint, -1,0,0
	dJointSetHingeAnchor joint, xp#-w#/2+lw#/2, yp#-th#/2, zp#-d#/2+ld#/2
	dJointSetHingeParam joint, dParamLoStop,  0
	dJointSetHingeParam joint, dParamHiStop,  0

	;create leg 2
	ode.odegeom = New odegeom
	ode\body = dBodyCreate(world)
	dBodySetPosition ode\body, xp#+w#/2-lw#/2, yp#-lh#/2-th#/2, zp#-d#/2+ld#/2
	dBodySetRotation ode\body, 0,0,0
	dBodySetAutoDisableFlag ode\body, 1
	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(space,lw#,lh#,ld#)
	dGeomSetBody ode\geom, ode\body	

	ode\mesh=CreateCube()
	EntityColor ode\mesh, 200,100,0
	ScaleMesh ode\mesh, lw#/2,lh#/2,ld#/2

	;join the legs to the table
	joint = dJointCreateHinge(world,0)
	dJointAttach joint, tableBody, ode\body
	dJointSetHingeAxis joint, -1,0,0
	dJointSetHingeAnchor joint, xp#+w#/2-lw#/2, yp#-th#/2, zp#-d#/2+ld#/2
	dJointSetHingeParam joint, dParamLoStop, -0.0
	dJointSetHingeParam joint, dParamHiStop,  0.0

	;create leg 3
	ode.odegeom = New odegeom
	ode\body = dBodyCreate(world)
	dBodySetPosition ode\body, xp#+w#/2-lw#/2, yp#-lh#/2-th#/2, zp#+d#/2-ld#/2
	dBodySetRotation ode\body, 0,0,0
	dBodySetAutoDisableFlag ode\body, 1
	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(space,lw#,lh#,ld#)
	dGeomSetBody ode\geom, ode\body	

	ode\mesh=CreateCube()
	EntityColor ode\mesh, 200,100,0
	ScaleMesh ode\mesh, lw#/2,lh#/2,ld#/2

	;join the legs to the table
	joint = dJointCreateHinge(world,0)
	dJointAttach joint, tableBody, ode\body
	dJointSetHingeAxis joint, -1,0,0
	dJointSetHingeAnchor joint, xp#+w#/2-lw#/2, yp#-th#/2, zp#+d#/2-ld#/2
	dJointSetHingeParam joint, dParamLoStop, -0.0
	dJointSetHingeParam joint, dParamHiStop,  0.0

	;create leg 4
	ode.odegeom = New odegeom
	ode\body = dBodyCreate(world)
	dBodySetPosition ode\body, xp#-w#/2+lw#/2, yp#-lh#/2-th#/2, zp#+d#/2-ld#/2
	dBodySetRotation ode\body, 0,0,0
	dBodySetAutoDisableFlag ode\body, 1
	dBodySetAutoDisableLinearThreshold ode\body, LINTHRESH
	dBodySetAutoDisableAngularThreshold ode\body, ANGTHRESH
	dBodySetAutoDisableSteps ode\body, STEPTHRESH

	ode\geom=dCreateBox(space,lw#,lh#,ld#)
	dGeomSetBody ode\geom, ode\body	

	ode\mesh=CreateCube()
	EntityColor ode\mesh, 200,100,0
	ScaleMesh ode\mesh, lw#/2,lh#/2,ld#/2

	;join the legs to the table
	joint = dJointCreateHinge(world,0)
	dJointAttach joint, tableBody, ode\body
	dJointSetHingeAxis joint, -1,0,0
	dJointSetHingeAnchor joint, xp#-w#/2+lw#/2, yp#-th#/2, zp#+d#/2-ld#/2
	dJointSetHingeParam joint, dParamLoStop, -0.0
	dJointSetHingeParam joint, dParamHiStop,  0.0

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

		;remove if object falls off the world
		If dGeomGetPositionY#(ode\geom) < -100 Then
			DebugLog "body "+Handle(ode)+" deleted"
			dGeomDestroy ode\geom
			dBodyDestroy ode\body
			FreeEntity ode\mesh
			Delete ode
		EndIf
	Next

End Function

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

Function JointLimits(limit)

For ode.ODEGeom=Each ODEGeom
	If dGeomIsEnabled(ode\geom)
		;If body=ode\body  ; specific body parts only
			numjoints=dBodyGetNumJoints(ode\body)
			If numjoints>0 
				For joints=0 To numjoints-1
					joint=dBodyGetJoint(ode\body,joints)
						If joint<>0 ; valid joints only
							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)
								
								; Check for sudden deceleration 
								If Abs((ode\LastForce#-forceA#))>limit Then
									;dJointAttach(joint,0,0)
									dJointDestroy joint
;									EmitSound break, ode\mesh
								End If

								ode\LastForce#=ForceA#
						
							End If

					End If
				Next
			End If
		;End If
	End If
Next

End Function