No problem. You might wanna use floats instead of doubles when using gl btw. I went doubles mad at first but I found it really slowed things down on my gpu. Not sure if modern cards are optimized for that kinda percision though.
Back to my problem, i now have the animator code complete, and although the actual pivots(entities) joints are animating correctly(I added a box to each joint to visually see it) the actual mesh deformation is kind of whacky.
It works fine frame 1. Perfectly looks like psonic's freaky zombie should but as soon as I go up the frames it starts to deform badly.
Please if you're reading mark let me know where i'm going wrong. You're probably the only one with enough knowledge of the b3d format here.
Here's the code that creates the matrix to deform each bone by.
Method UpdateAnim()
For Local s:tentity = EachIn subs
s.calculateWorldMatrix(Null)
Next
TEntity.TmpSurf = RenSurf
TEntity.Bas = VSurf
For Local s:TEntity = EachIn subs
s.TFormBones()
Next
End Method
Global TmpSurf:TSurface
Global Bas:TSurface
Method CalculateWorldMatrix(Parent:TMatrix)
Local Tmp:TMatrix = LocalRot.CreateCopy()
Tmp.Multiply( LocalTrans )
If Parent<>Null
Tmp.Multiply( Parent )
EndIf
World = Tmp.CreateCopy()
For Local s:Tentity = EachIn subs
s.calculateWorldMatrix( tmp )
Next
End Method
I multiply each entities rotation and translation matrices by it's parent (Exactly in the same order as the entity is visually drawn)
Then I call the deformer here which is supposed to transform the base surfaces vert into the visual surface based on each bone.
IT does not work, is an understatement.
Method TFormBones()
Local os:TSurface = TEntity.Bas
Local rs:TSurface = TEntity.TmpSurf
If Bone = Null
Return
EndIf
For Local j=0 Until bone.vc
Local Vert = bone.vertid[ j ]
World.GetPosition()
Local ox#,oy#,oz#
ox = world.x()
oy = world.y()
oz = world.z()
Local vx#,vy#,vz#
vx = os.vertexX( vert )
vy = os.vertexy( vert )
vz = os.vertexz( vert )
Local nx#,ny#,nz#
nx = vx - ox
ny = vy - oy
nz = vz - oz
world.tformvector( nx,ny,nz )
nx = world.tformx
ny = world.tformy
nz = world.tformz
vx = ox + nx
vy = oy + ny
vz = oz + nz
rs.moveVertex( vert,vx,vy,vz )
Next
For Local t:Tentity = EachIn subs
t.tformbones()
Next
End Method
Here's the code that computers the rotation postion based on the current anim time. IT slerps the rotation quat beween the left most and right most keyframes, and interpolates(I think that's the term) between the left and right anim frames position.
Scale is not yet implemeted because the model i'm using has no scale keys so it makes no difference.
Type TFrame
Field Rot:Quaternion
Field PosX#,posY#,posZ#
Field scalX#,scaly#,scalz#
Field Time#
Function MakeFrame:TFrame( L:TFrame,R:TFrame,Scal# )
Local out:TFrame = New tframe
out.rot = New quaternion
L.Rot.Slerp( out.rot,R.rot,scal )
'out.rot = l.rot
Local xd#,yd#,zd#
xd = r.posx-l.posx
yd = r.posy-l.posy
zd = r.posz-l.posz
out.posx = l.posx+xd*scal
out.posy = l.posy+yd*scal
out.posz = l.posz+zd*scal
Return out
End Function
End Type
Type TAnim
Field Frame:TFrame[3000],frames
Method FindLeft:TFrame( time# )
For Local j=time To 1 Step -1
If frame[j]<>Null
Return frame[j]
End If
Next
End Method
Method FindRight:TFrame( time#,Ignore:TFrame)
For Local j=time To frames
If frame[j]<>Null And frame[j]<>ignore
Return frame[j]
EndIf
Next
End Method
End Type
Method SetAnimTime( time# )
AnimTime = time
Print "SetAnimTime Called."
If animC <>Null
time = Time Mod AnimC.frames
If time<1 time =1
If time>animc.frames
mainlog.post("Mod failed.",True)
EndIf
For Local s:tentity = EachIn subs
s.SetFramer( time )
Next
Else
MainLog.Post("Entity has no aasscoiated animation tracks.",True)
EndIf
End Method
Method SetFramer(Time#)
If NoAnim = True Return
If animC<>Null
mainlog.post("Cannot directly animate top-tier entity.",True)
End If
Local LeftFrame:TFrame = Anim.FindLeft( Time )
Local RightFrame:TFrame = Anim.FindRight( Time,LeftFrame )
If leftFrame = RightFrame
cframe.rot = leftFrame.rot
cframe.posx = leftframe.posx
cframe.posy = leftframe.posy
cframe.posz = leftframe.posz
Else
Local dis# = RightFrame.time-LeftFrame.time
Local ltime# = time-leftframe.time
Local scal# = ltime/dis
cframe = TFrame.MakeFrame( LeftFrame,RightFrame,Scal )
cframe.rot.toAngles()
EndIf
localrot.rotate( cframe.rot.pitch,cframe.rot.yaw,cframe.rot.roll )
localtrans.position( cframe.posx,cframe.posy,cframe.posz )
For Local s:tentity = EachIn subs
s.setframer( time )
Next
End Method