Another Ragdoll problem

Blitz3D Forums/Blitz3D Programming/Another Ragdoll problem

I have managed to get a 3D Verlet Integrater and constraint system up and running OK, I can throw a chain of cubes around and they behave exactly how I would expect. I am now ready to move onto the next stage and construct a ragdoll, but this is were im stuck. To construct a ragdoll, I need to be able to place several particles/verlets on the one mesh ie a torso would require verlets placed at the shoulders, neck, top of the legs etc.
The current method im using is positionentity torso,x,y,z were x,y,z are the co-ordinates of the verlet, as you can see, using this method is OK if I only have to place the mesh at the position of one verlet, but I have to place the mesh at several positions simultaneously.

Im at work at the moment so haven't got the most uptodate code, but heres's a copy of what I have with me, it still shows the method that I am using.

Graphics3D 800,600,32,2
SetBuffer BackBuffer() 
light=CreateLight(2)
PositionEntity light,1000,1000,-100

Dim cube$(10)
cube(0)="a"
cube(1)="b"
cube(2)="c"
cube(3)="d"
cube(4)="e"
cube(5)="f"
cube(6)="g"
cube(7)="h"
cube(8)="i"
cube(9)="j"
cube(10)="k"

For a=0 To 10
cube(a)=CreateCube()
ScaleEntity cube(a),6,6,12
EntityColor cube(a),Rnd(1,256),Rnd(1,256),Rnd(1,256)
Next

Global cam=CreateCamera()
PositionEntity cam,500,50,-2000

;mirror=CreateMirror()

ov.verlet=New verlet
ov\x=20
ov\y=20
ov\z=20
ov\ox=20+Rnd(-2,2)
ov\oy=20+Rnd(-2,2)
ov\oz=0+Rnd(-2,2)

For i=1 To 10

	v.verlet=New verlet ; Create 10 Verlet's
	v\x=i*40+40
	v\y=40
	v\z=0
	v\ox=i*20+20+Rnd(-2,2) ;Old x position, fill with random position for very first loop
	v\oy=20+Rnd(-2,2)	 ;Old y position, fill with random position for very first loop
	v\oz=20
	v\size=20
	
		
	c.constraint=New constraint ; Create 10 Constraints
	c\Head=ov ; Connect one end of the constraint to the previous verlet
	c\Tail=v  ; Connect the other end of the Constraint to the new verlet
	c\Length=30 ; Constraint length
	ov=v
	
Next



SetBuffer BackBuffer()
While Not KeyHit(1)

If KeyHit(200) v\y=v\y*3 ; a simulated hit
If KeyHit(208) v\z=v\z+50


	Update ;Call Verlet Integrater and Rigid Constraint Function
	Draw   ;Call Function to draw verlets

	UpdateWorld
	RenderWorld
	
;Framecounter--------------------------------------------
    Framecounter_counter=Framecounter_counter+1
	If Framecounter_time=0 Then Framecounter_time=MilliSecs()
	    If Framecounter_time+1001 <MilliSecs() Then
		Framecounter_framerate=Framecounter_counter
		Framecounter_counter=0
		Framecounter_time=MilliSecs()
	EndIf
    Text 10,10,"fps: "+Framecounter_framerate
;--------------------------------------------------------

	Flip False
	
	;Cls
Wend

Type Verlet ; Define a Verlet
 Field x#, y#, z#, ox#, oy#, oz#, size
End Type

Type Constraint ; Define a Constraint
 Field Head.Verlet, Tail.Verlet, Length
End Type

;------ Verlet Integrater and Rigid Constraint Function ----------------------
Function Update() 
	For v.Verlet=Each Verlet	;Loop through each Verlet
		tx#=v\x ; Temp x
		ty#=v\y ; Temp y
		tz#=v\z
		v\x=v\x+.99*(v\x-v\ox)  ;give the verlet x momentum from the previous loop - decay the value
		v\y=v\y+.99*(v\y-v\oy)-.01 ;same as above (y momentum) plus gravity
		v\z=v\z+.99*(v\z-v\oz)  ;give the verlet x momentum from the previous loop - decay the value
		If v\x>GraphicsWidth()-v\size Then v\x=GraphicsWidth()-v\size ElseIf v\x<v\size Then v\x=v\size ; constrain verlet 
		If v\y>GraphicsHeight()-v\size Then v\y=GraphicsHeight()-v\size ElseIf v\y<v\size Then v\y=v\size ;  to screen
		v\ox=tx  ; store verlet x position in old slot for next loop
		v\oy=ty  ; store verlet y position in old slot for next loop
		v\oz=tz  ; store verlet z position in old slot for next loop
	Next
	
	For i=0 To 10 ;Iterate, can be reduced for speed, but less accurate
		For c.Constraint=Each Constraint	;Loop through each Constraint
			dx#=c\Tail\x-c\Head\x  ;x vector distance
			dy#=c\Tail\y-c\Head\y  ;y vector distance
			dz#=c\Tail\z-c\Head\z
			dl#=Sqr(dx*dx+dy*dy+dz*dz)   ;vector length
			d#=(dl-c\length)/Float(dl)  ; vector length - constraint / vector length
			dx#=dx/2	; half x distance
			dy#=dy/2	; half y distance
			dz#=dz/2
			c\Head\x=c\Head\x+d*dx; *.005 ;this will create a bouncy spring, adjust
			c\Head\y=c\Head\y+d*dy; *.005 ;this will create a bouncy spring, adjust
			c\Head\z=c\Head\z+d*dz; *.005 ;this will create a bouncy spring, adjust
			c\Tail\x=c\Tail\x-d*dx; *.005 ;this will create a bouncy spring, adjust
			c\Tail\y=c\Tail\y-d*dy; *.005 ;this will create a bouncy spring, adjust
			c\Tail\z=c\Tail\z-d*dz; *.005 ;ditto	;rigid constraint algorithm
		Next
	Next
End Function

Function Draw() ; loops through each verlet and draws at new position


a=0
	For v.verlet=Each verlet
		Color 255,0,0 ; colors the verlet white
		PositionEntity cube(a),v\x-v\size,v\y-v\size,v\z-v\size
		If a>0 PointEntity cube(a),cube(a-1); theres nothing to point the first cube at
		;may not need pointentity when verlets are moved to edge of mesh and 2 mesh's
		;share a verlet.
		;PointEntity cam,cube(a)
		a=a+1
	Next
		
End Function



I hope this Code box came out OK.
Any help appreciated.

I hate waiting, not getting any work done here, constantly refreshing the page to see if any replies have come in. I think I'll go for my lunch and see if any replies come in while im out of the office (hint, hint).

I think you need to make it clearer what you want. Are you going to make the ragdoll mesh within code or load a boned mesh?

If you're making it in code then it would be much easier to keep each constraint/limb as a separate entity.

Firstly create a temp mesh for your limb. Note that you need to offset the z axis, and make sure the depth of the mesh = 1 for this to work.

LIMB = createsphere()
positionmesh LIMB,0,0,1
scalemesh LIMB,1,1,.5

Add a new field into the contraint type so that you can store a copy of LIMB. Then in the update constraint phase simply position this limb at the head verlet. Pointentity the limb to the tail verlet. Then scaleentity on the z axis only based on the entitydistance between the two verlets.

You may want to store a thickness variable in the contraint type so that you can have a wider head etc.. Just apply this when your scaling the entity ..
e.g. scaleentity c\limb, c\thickness, c\thickness, entitydistance(... )

Thanks Stevie,
I will be modelling each limb as a seperate entity, but the problems im having is being able to place an entity (limb) at co-ordinates of multiple verlets simutaneously as in this picture



Like I said have a new limb for each constraint ... position it at one verlet , point it at the other and scale ... have you tried it?

@Nexus6
I don't understand what you want to do exactly, but if
you are trying to code a ragdoll character then you will
have bigger problems to resolve in the future ... such
as limiting the knee joint angles or detecting collision
within all the elements connected ...

Your code above works pretty good for a chain, but
if you are looking for a more complicated structure then
I would suggest having a look at one of the physics
engines we have around... Toka or ODE ...

just a thought...

Stevie, take the torso for instance, it is one limb or to be precice, one body part, yet it has many verlets and constraints, if i was to create a primitive for this, say a cube, I would still need to position that cube at every verlet that the torso is constructed........

Hold on, i think I know what you mean. Are you saying,,, the torso is made of 5 verlets and 9 constraints, but dont try and position the cube at all 5 verlets, just choose one. Now theres an idea, I'll give it a go.
My first thought was to parent a pivot at each position on the limb and then place thsese at the co-ordinates of the verlets, but that had many flaws.

Anyway I'll give that a go, let me know if im way off track.

@Eurythmia, I know I will have several problems with contraints, I have looked into dot product and other constraint algorithms, and they seem quite complicated. This is a learning exercise for me and also I would like to code some physics without resorting to additional dll's and learning new commands etc.

Anyway wish me luck, its getting an obsession this.

Yeah, obviously arms, legs and head will work as I suggest. You're probably better just creating a new verlet between the two lowest torsoe verlets, adding a few more contraints to stabilise it. Then you can position the torsoe there and point it at the neck verlet.

Personally, I use a pivot to represent each verlet. There are next to no overheads and you don't need to store the current x,y,z positions as you can use entityx( v\pivot ) etc... The added bonus is that you can set up collisions for each pivot. This is the method I use for the demo I posted a few days ago in the showcase.