Ok I have made a desicion to go back to the drawing board (I am really using a white board) unless I accidentally fix my old code. It will most likely be finished in a few days. I will base it on the verlet system which is the only system I know how to make.
If I encounter any problems and post on this blog, it will probably be completely different code than my old code. Wish me luck. I will post it when I am at least half-way finished. Thanks for the help.
@Pongo Have you added to your verlet system yet? It would be interesting to see how it is coming along.
P.S. I found some neat code in the archives that uses car.x from the driver sample file. here it is. :)
; 3D Verlet Functions
; from Thomas Jakobsen's "Advanced Character Physics"
; www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml
; Adapted for Blitz3D by Chris "Miracle" Casey, May 6 2003
;
; Added polymesh "cage" around verlet group and made constraint distance auto-calculating - Dave Cornish
; Need to make polymesh cage a collideable entity. I have had some minor success with this but its very complicated
; so it is left OUT of this version.
; Added player mesh and orient that mesh to the collision mesh
Graphics3D height,width,0,2
Const height=640
Const width=480
Const ACTIVE=1
Const radius#=.33333
Const size#=1.5
Const ITERATIONS = 5 ; How many loops through the "relaxation" routine, Lower = speed up / lose accuracy
Global fTimeStep#
Global vGrav.Vector = Vector(0.0,4,0.0) ; Gravity
Global Temp.Vector=Vector()
Global vTemp1.Vector = Vector(0,0,0) ; Some temporary vectors for calculations
Global vTemp2.Vector = Vector(0,0,0)
Global tol# = 0.001
Type Vector
Field x#
Field y#
Field z#
End Type
Type VerletPack ; Contains everything we need for basic physics
Field m.Vector ; Current position
Field old.Vector ; Last position
Field a.Vector ; Accumulated forces
Field radius# ; Collision radius from center
Field mass# ; Arbitrary mass unit
Field entity ; Placeholder for the 3D sphere
Field obj ; Which construct is this verlet a part of?
Field vertex ; vertex assigned to verlet
Field surface ; surface id from cube type
Field mesh ; mesh id from cube type
End Type
Type Constraint ; Two verlets connected by a mutual spring
Field v1.VerletPack
Field v2.VerletPack
Field d# ; Distance between verlets
End Type
Type cube
Field v.VerletPack[8]
Field player ; Player mesh
Field center.VerletPack ; Used to pisition player mesh
Field x1.VerletPack ; Used to orient player mesh to collision mesh/verlets
Field x2.VerletPack
Field z1.VerletPack
Field z2.VerletPack
Field X_vec# ; Junk for calculations
Field Y_vec#
Field Z_vec#
End Type
ClearTextureFilters
SetBuffer BackBuffer()
Collisions ACTIVE,ACTIVE,2,1
MoveMouse width/2,height/2
lgt = CreateLight()
cam = CreateCamera()
flr = CreateCube()
ScaleEntity flr,20,20,20
PositionEntity flr,0,10,0
EntityType flr,ACTIVE
grid_tex=CreateTexture( 256,256,1+4+8)
SetBuffer TextureBuffer( grid_tex )
ScaleTexture grid_tex,.2,.2
Color 255,255,255:Rect 0,0,256,256,False
grid_tex2=CreateTexture( 32,32,1)
SetBuffer TextureBuffer( grid_tex2 )
ScaleTexture grid_tex2,100,100
Color 0,0,60:Rect 0,0,32,32,False
EntityTexture flr,grid_tex,0,1
EntityTexture flr,grid_tex2,0,0
TextureBlend grid_tex,3
EntityFX flr,1
FlipMesh flr
SetBuffer BackBuffer()
For m = 1 To 10 ; Let's make some cubes!
xa# = 0
xb# = m*5 +5
xc# = 0
cc.cube = New cube
mesh=CreateMesh()
surface=CreateSurface(mesh)
cc\player=CreateCube();LoadMesh( "car.x" ) ; this can be loaded in the "Samples\Blitz 3D Samples\mak\driver"
FitMesh cc\player,-size,-size,-size,size*2,size*2,size*2
; Yes, all the below is necessary to create a stable 9-verlet "cube" ...
a.VerletPack = Verlet(xa - size, xb - size, xc - size, radius, 1.0, m, 0, 0, 0,surface,mesh,True)
b.VerletPack = Verlet(xa + size, xb - size, xc - size, radius, 1.0, m, 0, 0, 0,surface,mesh,True)
c.VerletPack = Verlet(xa + size, xb + size, xc - size, radius, 1.0, m, 255, 0, 0,surface,mesh,True)
d.VerletPack = Verlet(xa - size, xb + size, xc - size, radius, 1.0, m, 0, 255, 0,surface,mesh,True)
e.VerletPack = Verlet(xa - size, xb - size, xc + size, radius, 1.0, m, 0, 0, 0,surface,mesh,True)
f.VerletPack = Verlet(xa + size, xb - size, xc + size, radius, 1.0, m, 0, 0, 0,surface,mesh,True)
g.VerletPack = Verlet(xa + size, xb + size, xc + size, radius, 1.0, m, 0, 0, 255,surface,mesh,True)
h.VerletPack = Verlet(xa - size, xb + size, xc + size, radius, 1.0, m, 0, 0, 0,surface,mesh,True)
i.VerletPack = Verlet(xa, xb, xc,size, 1.0, m, 255, 255, 255,surface,mesh,True)
AddTriangle(surface,0,2,1)
AddTriangle(surface,0,3,2)
AddTriangle(surface,0,1,5)
AddTriangle(surface,0,5,4)
AddTriangle(surface,0,4,7)
AddTriangle(surface,0,7,3)
AddTriangle(surface,6,1,2)
AddTriangle(surface,6,2,3)
AddTriangle(surface,6,5,1)
AddTriangle(surface,6,4,5)
AddTriangle(surface,6,7,4)
AddTriangle(surface,6,3,7)
UpdateNormals mesh
EntityType mesh,0
EntityColor mesh,255,0,0
EntityAlpha mesh,0
; Edges - distance 1.0
Constraint2(a,b)
Constraint2(b,c)
Constraint2(a,d)
Constraint2(c,d)
Constraint2(e,f)
Constraint2(f,g)
Constraint2(e,h)
Constraint2(g,h)
Constraint2(a,e)
Constraint2(b,f)
Constraint2(c,g)
Constraint2(d,h)
; Cross-faces - distance ~Sqr(2.0)
Constraint2(a,c)
Constraint2(b,d)
Constraint2(e,g)
Constraint2(f,h)
Constraint2(a,f)
Constraint2(a,h)
Constraint2(b,e)
Constraint2(b,g)
Constraint2(c,f)
Constraint2(c,h)
Constraint2(d,e)
Constraint2(d,g)
; Diagonals - distance ~Sqr(3.0)
Constraint2(a,g)
Constraint2(b,h)
Constraint2(c,e)
Constraint2(d,f)
; Constraining the center sphere - distance ~0.5 * Sqr(3.0)
Constraint2(a,i)
Constraint2(b,i)
Constraint2(c,i)
Constraint2(d,i)
Constraint2(e,i)
Constraint2(f,i)
Constraint2(g,i)
Constraint2(h,i)
cc\v[0] = i
cc\v[1] = a
cc\v[2] = b
cc\v[3] = c
cc\v[4] = d
cc\v[5] = e
cc\v[6] = f
cc\v[7] = g
cc\v[8] = h
; Set up variables used for player mesh
cc\center=i
cc\x1=c
cc\x2=d
cc\z1=g
cc\z2=c
Next
;********* functions defined ********************************************
Function TimeStep() ; The main loop
AccumulateForces()
DoVerlet()
SatisfyConstraints2()
End Function
Function AccumulateForces() ; As of right now, we only accumulate gravity
For v.VerletPack = Each VerletPack
CloneVector(v\a,vGrav)
Next
End Function
Function DoVerlet()
For v.VerletPack = Each VerletPack
CloneVector(vTemp1,v\m)
MulVecScalar(vTemp2,v\a,fTimeStep * fTimeStep) ; a * timestep * timestep
AddVector2(v\old,vTemp2) ; old = old + a * ts * ts
SubVector2(v\m,v\old) ; m = m - old + a * ts * ts
AddVector2(v\m,vTemp1) ; m += m - old + a * ts * ts
CloneVector(v\old,vTemp1)
Next
End Function
Function SatisfyConstraints2()
For n = 1 To ITERATIONS
For c.Constraint = Each Constraint
SetDistance(c\v1,c\v2,c\d)
Next
For cc.cube = Each cube
bing = 0
q.cube = cc
While bing = 0
If q <> Last cube
q = After q
dp# = ((cc\v[0]\m\x - q\v[0]\m\x) * (cc\v[0]\m\x - q\v[0]\m\x)) + ((cc\v[0]\m\y - q\v[0]\m\y) * (cc\v[0]\m\y - q\v[0]\m\y)) + ((cc\v[0]\m\z - q\v[0]\m\z) * (cc\v[0]\m\z - q\v[0]\m\z))
If dp < 6.0
For aa = 0 To 8
For bb = 0 To 8
l# = cc\v[aa]\radius + q\v[bb]\radius
dp2# = ((cc\v[aa]\m\x - q\v[bb]\m\x) * (cc\v[aa]\m\x - q\v[bb]\m\x)) + ((cc\v[aa]\m\y - q\v[bb]\m\y) * (cc\v[aa]\m\y - q\v[bb]\m\y)) + ((cc\v[aa]\m\z - q\v[bb]\m\z) * (cc\v[aa]\m\z - q\v[bb]\m\z))
If dp2 < (l * l)
SetDistance(cc\v[aa],q\v[bb],l)
SubVector(vTemp1,cc\v[aa]\m,cc\v[aa]\old)
MulVecScalar2(vTemp1,.4 * fTimeStep)
AddVector2(cc\v[aa]\old,vTemp1)
EndIf
Next
Next
EndIf
Else
bing = 1
EndIf
Wend
Next
Next
End Function
Function SetDistance(v1.VerletPack,v2.VerletPack,dist#)
SubVector(vTemp1,v1\m,v2\m)
deltalength# = Sqr((vTemp1\x * vTemp1\x) + (vTemp1\y * vTemp1\y) + (vTemp1\z * vTemp1\z))
If deltalength <= 0.0 deltalength = 0.0001
diff# = (deltalength - dist) / deltalength
tmass# = v1\mass + v2\mass
MulVecScalar(vTemp2,vTemp1,diff * (v2\mass / tmass))
SubVector2(v1\m,vTemp2)
MulVecScalar(vTemp2,vTemp1,diff * (v1\mass / tmass))
AddVector2(v2\m,vTemp2)
End Function
Function CageVerlet2(v.VerletPack) ; Collision code
col = False
If v\m\x <> EntityX(v\entity)
v\m\x=EntityX(v\entity)
col = True
EndIf
If v\m\y <> EntityY(v\entity)
v\m\y=EntityY(v\entity)
col = True
EndIf
If v\m\z <> EntityZ(v\entity)
v\m\z=EntityZ(v\entity)
col = True
EndIf
If col
SubVector(vTemp1,v\m,v\old)
MulVecScalar2(vTemp1,0.4 * fTimeStep)
AddVector2(v\old,vTemp1)
EndIf
End Function
Function Verlet.VerletPack(x#,y#,z#,radius#, mass# = 1.0, obj%, red,green,blue,surface,mesh,state)
v.VerletPack = New VerletPack
v\surface=surface
v\mesh=mesh
v\vertex=AddVertex(v\surface,x,y,z)
v\m = Vector(x,y,z)
v\entity = CreatePivot()
PositionEntity v\entity,x,y,z
EntityType v\entity, ACTIVE
EntityRadius v\entity,radius#
v\old = Vector(x,y,z)
v\a = Vector(0.0,0.0,0.0)
If radius <= 0.0 radius = 0.01
v\radius = radius
If mass <= 0.0 mass = 0.01
v\mass = mass
v\obj = obj
Return v
End Function
Function Constraint2.Constraint(v1.VerletPack,v2.VerletPack)
c.Constraint = New Constraint
c\v1 = v1
c\v2 = v2
c\d = Sqr((v2\m\x - v1\m\x)^2 + (v2\m\y - v1\m\y)^2 + (v2\m\z - v1\m\z)^2)
;Return c ; You may need this someday ... we don't for what we have here
End Function
;// Create a Vector
Function Vector.Vector(x#=0.0,y#=0.0,z#=0.0)
v.Vector = New Vector
v\x=x
v\y=y
v\z=z
Return v
End Function
;// Vector 1 is set to Vector 2
Function CloneVector(v1.Vector,v2.Vector)
v1\x = v2\x
v1\y = v2\y
v1\z = v2\z
End Function
;// Vector Scalar Multiplication
;// Form of Vector1 = Vector2 * Scalar
Function MulVecScalar(v1.Vector,v2.Vector,s#)
v1\x = v2\x * s
v1\y = v2\y * s
v1\z = v2\z * s
End Function
;// Form of Vector1 = Vector1 + Vector2
Function AddVector2(v1.Vector,v2.Vector)
v1\x = v1\x + v2\x
v1\y = v1\y + v2\y
v1\z = v1\z + v2\z
End Function
;// Form of Vector1 = Vector1 - Vector2
Function SubVector2(v1.Vector,v2.Vector)
v1\x = v1\x - v2\x
v1\y = v1\y - v2\y
v1\z = v1\z - v2\z
End Function
;// Vector Subtraction
;// Form of Vector1 = Vector2 - Vector3
Function SubVector(v1.Vector,v2.Vector,v3.Vector)
v1\x = v2\x - v3\x
v1\y = v2\y - v3\y
v1\z = v2\z - v3\z
End Function
;// Form of Vector1 = Vector1 * Scalar
Function MulVecScalar2(v1.Vector,s#)
v1\x = v1\x * s
v1\y = v1\y * s
v1\z = v1\z * s
End Function
;************* deltatime function ******************
Global new_time=MilliSecs(), old_time=MilliSecs()
Function delta_time#(new_time)
delta_t#=(new_time - old_time) * .001
old_time=new_time
Return delta_t#
End Function
;**************** main loop ***************************************
While Not KeyHit(1)
fTimeStep#=delta_time(MilliSecs())
TimeStep()
For v.VerletPack = Each VerletPack
VertexCoords v\surface,v\vertex,v\m\x,v\m\y,v\m\z
UpdateNormals v\mesh
PositionEntity v\entity,v\m\x,v\m\y,v\m\z
Next
For temp_cube.cube = Each cube
PositionEntity temp_cube\player,EntityX(temp_cube\center\entity),EntityY(temp_cube\center\entity),EntityZ(temp_cube\center\entity)
temp_cube\X_vec=EntityX(temp_cube\x1\entity)-EntityX(temp_cube\x2\entity)
temp_cube\Y_vec=EntityY(temp_cube\x1\entity)-EntityY(temp_cube\x2\entity)
temp_cube\Z_vec=EntityZ(temp_cube\x1\entity)-EntityZ(temp_cube\x2\entity)
AlignToVector temp_cube\player, temp_cube\X_vec, temp_cube\Y_vec, temp_cube\Z_vec, 1
temp_cube\X_vec=EntityX(temp_cube\z1\entity)-EntityX(temp_cube\z2\entity)
temp_cube\Y_vec=EntityY(temp_cube\z1\entity)-EntityY(temp_cube\z2\entity)
temp_cube\Z_vec=EntityZ(temp_cube\z1\entity)-EntityZ(temp_cube\z2\entity)
AlignToVector temp_cube\player, temp_cube\X_vec, temp_cube\Y_vec, temp_cube\Z_vec, 3
Next
UpdateWorld
For v.VerletPack = Each VerletPack
CageVerlet2(v)
Next
PositionEntity cam,0,0,0
RotateEntity cam,MouseY()-height*.5 ,(-MouseX())-width*.5+50,0
MoveEntity cam,0,0,-15
RenderWorld
Flip False
Wend
End