I don't have time to pursue this. Maybe someone else can add the rigid bodies. I had some success with making objects out of cross-linked chains, but it got to be too many chains for even a simple cube.
The missing code is the part that adjusts the rotation of the object. I suggest building off of what i have, rather than doing a whole new routine.
Do not ask me for support.
Demo program:
Include "physics.bb"
Graphics3D 800,600,16,2
SetBuffer BackBuffer()
Global cam=CreateCamera()
MoveEntity cam,0,30,-45
TurnEntity cam,35,0,0
;MoveEntity cam,0,0,-24
g=LoadMesh("start.b3d")
ScaleMesh g,.10,.10,.10
MoveEntity g,0,-15,30
;RotateEntity g,0,0,5
;g=CreatePlane()
EntityType g,2
;MoveEntity g,0,-10,0
;EntityColor g,100,100,100
;
For n=1 To 0
g=CreateCube()
RotateEntity g,0,90+45,0
MoveEntity g,2*n+50,-10+n*2,-50
ScaleEntity g,1,1,100
EntityType g,2
EntityColor g,100,100,100
Next
;g=CreateCube()
;ScaleMesh g,20,20,20
;MoveEntity g,0,0,20
;FlipMesh g
r#=1.5
m=CreateSphere()
EntityShininess m,1
EntityType m,1
EntityRadius m,r
ScaleMesh m,r,r,r
HideEntity m
l=CreateLight()
RotateEntity l,25,45,0
EntityParent l,cam
Collisions 1,2,2,2
Collisions 1,1,1,2
link=CreateSphere()
EntityType link,1
EntityRadius link,1
HideEntity link
For m=1 To 6
For n=1 To 6
link=CopyEntity(link)
EntityColor link,Rand(255),Rand(255),Rand(255)
If n=1
firstlink=link
;entitymass link,100000
PositionEntity link,Rnd(-32,33),20,Rnd(-32,32)
EndIf
If n=1 And m<>6
ScaleEntity link,2,2,2
EntityRadius link,2
enablephysics link,0
entitymass link,100000
Else
PositionEntity link,EntityX(firstlink),20-5*n,EntityZ(firstlink)
ScaleEntity link,r,r,r
EntityRadius link,r
enablephysics link,11
;entityelasticity link,0.9
entityfriction link,0.01
EndIf
If n=2
chain=createchain(link,lastlink,5)
EndIf
If n>2
chain=createchain(link,lastlink,5)
EndIf
lastlink=link
Next
;If ll<>0 And m<>6 createchain ll,firstlink,5
ll=link
Next
entitymass link,20
rb.rigidbody=New rigidbody
ball=CopyMesh(link)
ScaleEntity ball,1,1,1
EntityType ball,0
rb\mesh=ball
Include "CreateRigidCube.bb"
ball=CopyMesh(link)
ScaleEntity ball,2,2,2
EntityType ball,1
EntityRadius ball,2
MoveEntity ball,5,0,0
EntityColor ball,255,0,0
ph.physics=enablephysics(ball,11)
ph\body=rb
entityelasticity ball,0.9
entityfriction ball,0.01
ball=CopyMesh(link)
ScaleEntity ball,2,2,2
EntityType ball,1
EntityRadius ball,2
MoveEntity ball,-5,0,0
EntityColor ball,255,0,0
ph.physics=enablephysics(ball,11)
ph\body=rb
entityelasticity ball,0.9
entityfriction ball,0.01
period=1000/60
time=MilliSecs()-period
While Not KeyHit(1)
Repeat
elapsed=MilliSecs()-time
Until elapsed
ticks=elapsed/period
tween#=Float(elapsed Mod period)/Float(period)
For k=1 To ticks
time=time+period
If KeyDown(28)
;r=Rand(2)+1
r=3
ball=CopyMesh(link)
ScaleEntity ball,r,r,r
EntityRadius ball,r
EntityType ball,1
PositionEntity ball,Rnd(-20,20),Rnd(20),Rnd(-20,20)
enablephysics ball,11
entitymass ball,2;r^2
EntityElasticity ball,0.98
EntityColor ball,Rand(255),Rand(255),Rand(255)
EntityFriction ball,0.01
MoveEntity ball,Rnd(-2,2),Rnd(-2,2),Rnd(-2,2)
balls=balls+1
If lastball
;If Rand(2)=1 createchain lastball,ball,10
lastball=0
Else
lastball=ball
EndIf
EndIf
TranslateEntity link,0.05*(KeyDown(205)-KeyDown(203)),0.5*KeyDown(16),0.05*(KeyDown(200)-KeyDown(208))
UpdatePhysics 1
Next
RenderWorld
Text 0,0,fps()
Text 0,20,"Press Q to lift chain."
Text 0,40,"Arrow keys move chain"
Text 0,60,"Press enter to add balls."
Text 0,80,balls+" balls."
Flip
Wend
Global FPS_fpstime
Function FPS()
oldtime=FPS_fpstime
FPS_fpstime=MilliSecs()
elapsed=FPS_fpstime-oldtime
If Not elapsed elapsed=1
FPS_fps=1000/elapsed
Return FPS_FPS
End Function
Physics routines ("physics.bb"):
Type bond
Field mesh
Field a.physics, b.physics
Field length#
Field nextlink.bond
Field updated
Field offsetA#
Field offsetb#
End Type
Type rigidbody
Field mesh
Field points
End Type
Type physics
Field mesh
Field velocity#[5]
Field elasticity#
Field mass#
Field flags
Field friction#[1]
Field position#[5]
Field compression#[1]
Field dvelocity#[5]
Field offset#[2]
Field body.rigidbody
End Type
Function CreateChain(a,b,length#)
ph.physics=findphysics(a)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph2.physics=findphysics(b)
If ph2=Null RuntimeError "Entity does not have physics enabled."
l.bond=New bond
l\mesh=CreateCube()
l\a=ph
l\b=ph2
l\length=length
loffseta=Rnd(-90,90)
loffsetb=Rnd(-90,90)
Return Handle(l)
End Function
Function AddLink(chain,link,length#)
ph.physics=findphysics(link)
If ph=Null RuntimeError "Entity does not have physics enabled."
l2.bond=Object.bond(chain)
l.bond=New bond
l2\nextlink=l
l\mesh=CreateCube()
l\a=l2\b
l\b=ph
l\length=length/2
Return Handle(l)
End Function
Function UpdatePhysics(detail=2)
For ph.physics=Each physics
;update velocity
If 2^0 And ph\flags
If 2^3 And ph\flags
ph\velocity[0]=ph\velocity[0]+EntityX(ph\mesh,1)-ph\position[0]
ph\velocity[1]=ph\velocity[1]+EntityY(ph\mesh,1)-ph\position[1]
ph\velocity[2]=ph\velocity[2]+EntityZ(ph\mesh,1)-ph\position[2]
EndIf
EndIf
ph\position[0]=EntityX(ph\mesh,1)
ph\position[1]=EntityY(ph\mesh,1)
ph\position[2]=EntityZ(ph\mesh,1)
;gravity
If 2^1 And ph\flags
ph\velocity[1]=ph\velocity[1]-0.05
EndIf
;execute translational velocity
If 2^0 And ph\flags
TranslateEntity ph\mesh,ph\velocity[0],ph\velocity[1],ph\velocity[2],1
;TranslateEntity ph\mesh,Rnd(-0.00001,0.00001),Rnd(-0.0001,0.0001),Rnd(-0.0001,0.0001),1
EndIf
;execute rotational velocity
If 2^2 And ph\flags TurnEntity ph\mesh,ph\velocity[3],ph\velocity[4],ph\velocity[5],1
ph\position[3]=EntityX(ph\mesh,1)
ph\position[4]=EntityY(ph\mesh,1)
ph\position[5]=EntityZ(ph\mesh,1)
Next
UpdateWorld
For ph.physics=Each physics
ph\velocity[3]=ph\velocity[0]
ph\velocity[4]=ph\velocity[1]
ph\velocity[5]=ph\velocity[2]
ph\velocity[0]=EntityX(ph\mesh,1)-ph\position[0]
ph\velocity[1]=EntityY(ph\mesh,1)-ph\position[1]
ph\velocity[2]=EntityZ(ph\mesh,1)-ph\position[2]
Next
;transfer inertia
For ph.physics=Each physics
vx#=ph\velocity[3]-ph\velocity[0]
vy#=ph\velocity[4]-ph\velocity[1]
vz#=ph\velocity[5]-ph\velocity[2]
For c=1 To CountCollisions(ph\mesh)
collider=CollisionEntity(ph\mesh,c)
x#=CollisionX(ph\mesh,c)
y#=CollisionY(ph\mesh,c)
z#=CollisionZ(ph\mesh,c)
nx#=Abs(CollisionNX(ph\mesh,c))
ny#=Abs(CollisionNY(ph\mesh,c))
nz#=Abs(CollisionNZ(ph\mesh,c))
Select GetEntityType(collider)
; ;Spheres
Case 1
k#=0.5
ph2.physics=findphysics(collider)
If ph2<>Null
ph2\velocity[0]=ph2\velocity[0]+vx*k*ph\mass/ph2\mass
ph2\velocity[1]=ph2\velocity[1]+vy*k*ph\mass/ph2\mass
ph2\velocity[2]=ph2\velocity[2]+vz*k*ph\mass/ph2\mass
Exit
EndIf
;Polygons with infinite mass
Case 2
k#=0.8
If k*nx*Abs(ph\velocity[3])>Abs(ph\velocity[0]) ph\velocity[0]=ph\velocity[0]*(1.-k*nx)-ph\velocity[3]*nx*k
If k*ny*Abs(ph\velocity[4])>Abs(ph\velocity[1]) ph\velocity[1]=ph\velocity[1]*(1.-k*ny)-ph\velocity[4]*ny*k
If k*nz*Abs(ph\velocity[5])>Abs(ph\velocity[2]) ph\velocity[2]=ph\velocity[2]*(1.-k*nz)-ph\velocity[5]*nz*k
End Select
Next
Next
;add friction
For ph.physics=Each physics
If EntityCollided(ph\mesh,2)
For n=0 To 5
;sliding friction
ph\velocity[n]=ph\velocity[n]*ph\friction[0]
;static friction
If Abs(ph\velocity[n])<ph\friction[1] ph\velocity[n]=0.0
Next
EndIf
Next
;save positions for automatic velocity updating
For ph.physics=Each physics
ph\position[0]=EntityX(ph\mesh,1)
ph\position[1]=EntityY(ph\mesh,1)
ph\position[2]=EntityZ(ph\mesh,1)
Next
;handle chains
For b.bond=Each bond
ScaleEntity b\mesh,1,1,1
fma#=b\a\mass/(b\a\mass+b\b\mass)
fmb#=b\b\mass/(b\a\mass+b\b\mass)
PositionEntity b\mesh,EntityX(b\a\mesh,1)*fma+EntityX(b\b\mesh,1)*fmb,EntityY(b\a\mesh,1)*fma+EntityY(b\b\mesh,1)*fmb,EntityZ(b\a\mesh,1)*fma+EntityZ(b\b\mesh,1)*fmb
AlignToVector b\mesh,EntityX(b\a\mesh,1)-EntityX(b\b\mesh,1),EntityY(b\a\mesh,1)-EntityY(b\b\mesh,1),EntityZ(b\a\mesh,1)-EntityZ(b\b\mesh,1),3
MoveEntity b\mesh,0,0,(0.5-fma)*b\length
TFormPoint 0,0,b\length/2.0,b\mesh,0
PositionEntity b\a\mesh,TFormedX(),TFormedY(),TFormedZ(),1
TFormPoint 0,0,-b\length/2.0,b\mesh,0
PositionEntity b\b\mesh,TFormedX(),TFormedY(),TFormedZ(),1
ScaleEntity b\mesh,.25,.25,0.5*pointdistance(EntityX(b\b\mesh,1),EntityY(b\b\mesh,1),EntityZ(b\b\mesh,1),EntityX(b\a\mesh,1),EntityY(b\a\mesh,1),EntityZ(b\a\mesh,1))
Next
For rb.rigidbody=Each rigidbody
x#=0.0
y#=0.0
z#=0.0
yaw#=0.0
n=0
For ph.physics=Each physics
If ph\body=rb
x=x+EntityX(ph\mesh,1)
y=y+EntityY(ph\mesh,1)
z=z+EntityZ(ph\mesh,1)
TFormPoint ph\offset[0],ph\offset[1],ph\offset[2],rb\mesh,0
dx#=EntityX(ph\mesh,1)-EntityX(rb\mesh,1)
dy#=EntityY(ph\mesh,1)-EntityY(rb\mesh,1)
dz#=EntityZ(ph\mesh,1)-EntityZ(rb\mesh,1)
Normalize dx,dy,dz
If n=0 AlignToVector rb\mesh,dx,0,dz,1 Else AlignToVector rb\mesh,-dx,0,-dz,1
If EntityYaw(rb\mesh,1)<0.0 yu=360.0+EntityYaw(rb\mesh,1) Else yu=EntityYaw(rb\mesh,1)
yaw=yaw+yu
n=n+1
EndIf
Next
x=x/Float(n)
y=y/Float(n)
z=z/Float(n)
yaw=yaw/Float(n)
PositionEntity rb\mesh,x,y,z,1
RotateEntity rb\mesh,0,yaw,0,1
For ph.physics=Each physics
If ph\body=rb
TFormPoint ph\offset[0],ph\offset[1],ph\offset[2],rb\mesh,0
PositionEntity ph\mesh,TFormedX(),TFormedY(),TFormedZ()
EndIf
Next
Next
End Function
Function MoveLinks(entity,x#,y#,z#)
If KeyDown(57)
For b.bond=Each bond
If b\updated=False
If b\a\mesh=entity
TranslateEntity b\b\mesh,x,y,z,1
b\updated=True
movelinks b\b\mesh,x,y,z
ElseIf b\b\mesh=entity
TranslateEntity b\a\mesh,x,y,z,1
b\updated=True
movelinks b\a\mesh,x,y,z
EndIf
EndIf
Next
EndIf
End Function
Function CreateVerletCube()
End Function
Function EntityCompression(ease#,max#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\Compression[0]=ease
ph\Compression[1]=max
End Function
Function PointDistance#( x1#,y1#,z1#,x2#,y2#,z2# )
Return Sqr#((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
End Function
Function EntityFriction(e,sliding#,static#=0.0001)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\friction[0]=1.0-sliding
ph\friction[1]=static
End Function
Function FindPhysics.physics(e)
For ph.physics=Each physics
If ph\mesh=e Return ph
Next
Return Null
End Function
Function EnablePhysics.physics(e,flags=9)
ph.physics=findphysics(e)
If ph=Null ph=New physics
For n=0 To 5
ph\velocity[n]=0
Next
ph\mesh=e
ph\mass=1.0
ph\elasticity=0.0
ph\flags=flags
ph\friction[0]=0.9
ph\friction[1]=0.001
ResetEntity e
ph\position[0]=EntityX(e,1)
ph\position[1]=EntityY(e,1)
ph\position[2]=EntityZ(e,1)
ph\compression[0]=0.8
ph\compression[1]=1.5
ph\offset[0]=EntityX(e)
ph\offset[1]=EntityY(e)
ph\offset[2]=EntityZ(e)
Return ph
End Function
Function DisablePhysics(e)
ph.physics=findphysics(e)
If ph<>Null Delete ph
End Function
Function EntityElasticity(e,m#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\Elasticity=m
End Function
Function AccelerateEntity(e,x#,y#,z#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\velocity[0]=ph\velocity[0]+x
ph\velocity[1]=ph\velocity[1]+y
ph\velocity[2]=ph\velocity[2]+z
End Function
Function EntityVelocity(e,x#,y#,z#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\velocity[0]=x
ph\velocity[1]=y
ph\velocity[2]=z
End Function
Function EntityInertia(e,x#,y#,z#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\velocity[0]=x/ph\mass
ph\velocity[1]=y/ph\mass
ph\velocity[2]=z/ph\mass
End Function
Function EntityMass(e,m#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
ph\mass=m
End Function
Function GetEntityMass#(e,m#)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\mass
End Function
Function EntityInertiaX#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\mass*ph\velocity[0]
End Function
Function EntityInertiaY#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\mass*ph\velocity[1]
End Function
Function EntityInertiaZ#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\mass*ph\velocity[2]
End Function
Function EntityVelocityX#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\velocity[0]
End Function
Function EntityVelocityY#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\velocity[1]
End Function
Function EntityVelocityZ#(e)
ph.physics=findphysics(e)
If ph=Null RuntimeError "Entity does not have physics enabled."
Return ph\velocity[2]
End Function
|