I've been trying to work something out to find b3d vertex positions. It works up to a point on the model i tested it with. But the arms are still wrong, they somehow stay in their original position and move only a bit.
I've used the emo girl from clownhunters emo game 2.
http://www.codersworkshop.com/viewpost.php?id=78609 (if i post a direct link, the codebox get scrambled)
;internal counters
Global numc%
;will contain the number of children
Global count_children%
;setup graphics
Graphics3D 640, 480, 0, 2
SetBuffer BackBuffer()
;create camera
camera = CreateCamera()
PositionEntity camera, 0, 20, -100
CameraZoom camera, 2.4
;i've used this on a single surface b3d file
;it is the emo girl from clownhunters game (v2).
;http://www.codersworkshop.com/viewpost.php?id=78609
Const meshfilename$ = "emo girl.b3d"
;Load anim mesh
mesh = LoadAnimMesh(meshfilename$)
Animate mesh, 1, 1
;create cursor prototype
ocursor = CreateSphere()
ScaleMesh ocursor, 0.4, 0.4, 0.4
EntityColor ocursor, 255, 0, 0
EntityFX ocursor, 1
EntityOrder ocursor, -1
HideEntity ocursor
;count children
count_children% = EnumerateChildren(mesh)
;make room
Dim enumChild%(count_children)
Dim enumName$(count_children)
Dim x1#(count_children)
Dim y1#(count_children)
Dim z1#(count_children)
;store children
EnumerateChildren(mesh, True)
Print "Found using recursive EnumerateChildren:"
;print out all enumerated children
For i = 0 To count_children%
;write name
Write EntityName$(enumChild%(i))
;write parent structure
p = enumChild%(i)
While (GetParent(p) <> 0)
p = GetParent(p)
Write "->" + EntityName$(p)
Wend
Print
Next
;!!!!!!!!!!!!!!!!!!!!!!!! - i tested this on a single surface model, so no idea how the
; count vertices
;!!!!!!!!!!!!!!!!!!!!!!!! - other vertices are indexed, i assumed the counter kept increasing
cv% = 0
For i = 1 To CountSurfaces(mesh)
surf% = GetSurface(mesh, i)
cv% = cv% + CountVertices(surf%)
Next
;set array sizes
Dim joints#(count_children%, cv%)
Dim parents(cv, 10) ;store parents (max parents = 10)
Dim max(cv) ;number of parents
;parse file
ff = ReadFile(meshfilename$)
Print "Found parsing file:"
While Not(Eof(ff))
s$ = Chr$(ReadByte(ff))
;search for "N"
If s$ = "N" Then
;read next 3 characters
s$ = "N" + Chr$(ReadByte(ff)) + Chr$(ReadByte(ff)) + Chr$(ReadByte(ff))
;search for "NODE"
If s$ = "NODE" Then
n$ = "": cc$ = "X"
length = ReadInt(ff)
cc$ = "": n$ = ""
While cc$ <> Chr$(0)
n$ = n$ + cc$
cc$ = Chr$(ReadByte(ff))
Wend
Print n$
End If
End If
;search for "B"
If s$ = "B" Then
;read next 3 characters
s$ = "B" + Chr$(ReadByte(ff)) + Chr$(ReadByte(ff)) + Chr$(ReadByte(ff))
;search for "BONE"
If s$ = "BONE" Then
;inc bone counter
boneindex = boneindex + 1
;read all vertices affected by the bone
length = ReadInt(ff)
For i = 1 To length / 8
;read vertex index
vindex% = ReadInt(ff)
;read weight
joints#(boneindex, vindex%) = ReadFloat(ff)
;link parent to vertex
parents(vindex, max(vindex)) = boneindex
;increase number of parents for vertex
max(vindex) = max(vindex) + 1
Next
End If
End If
Wend
CloseFile ff
;will contain the pivots
Dim cursor%(cv, 10)
;create visible red spheres
surf = GetSurface(mesh, 1)
Dim show(cv)
For i = 0 To cv% - 1
show(i) = CopyEntity(ocursor)
Next
;create a pivot for each vertex, for each parent
For i = 0 To cv% - 1
For j = 0 To max(i)
cursor(i, j) = CreatePivot()
;place it on vertex
PositionEntity cursor(i, j), VertexX(surf, i), VertexY(surf, i), VertexZ(surf, i)
l_parent% = enumChild(parents(i, j))
l_rx# = EntityPitch(l_parent,1)
l_ry# = EntityYaw(l_parent,1)
l_rz# = EntityRoll(l_parent,1)
RotateEntity l_parent,0,0,0,1
EntityParent cursor(i, j),l_parent
RotateEntity l_parent,l_rx,l_ry,l_rz,1
Next
Next
WaitKey()
;main loop
While Not KeyDown(1)
;render world
UpdateWorld
RenderWorld
;scan all vertices
For i = 0 To cv% - 1
;reset output coordinates to 0
xx# = 0
yy# = 0
zz# = 0
;scan all parent joints
For j = max(i) To 0 Step -1
;store parent
oldp% = GetParent(cursor(i, j))
;reset parent
EntityParent cursor(i, j), 0
;transform point to real world
TFormPoint EntityX(cursor(i, j)), EntityY(cursor(i, j)), EntityZ(cursor(i, j)), 0, 0;cursor(i, j), 0
;find this parent
fnd = parents(i, j)
If fnd > 0 Then
;add the coordinates in the amount, stored in "joints"
xx# = (xx) + (TFormedX() * joints(fnd, i))
yy# = (yy) + (TFormedY() * joints(fnd, i))
zz# = (zz) + (TFormedZ() * joints(fnd, i))
End If
;reset parent
EntityParent cursor(i, j), oldp
Next
;place a red dot on the calculated point
;CameraProject camera, xx, yy, zz
;Rect ProjectedX(), ProjectedY(), 5, 5
PositionEntity show(i), xx, yy, zz
Next
;turn 3d object
TurnEntity mesh, 0, 1, 0
Flip
Wend
End
;-----------------------------------------------------------------------------------------------------
; EnumerateChildren()
;-----------------------------------------------------------------------------------------------------
;recursively enumerate children
Function EnumerateChildren%(mesh%, store% = False, reset% = True)
;set counter
If Not reset Then numc% = numc% + 1 Else numc% = 0
;store mesh
If store Then enumChild(numc%) = mesh
;recursively enumerate all children
For i = 1 To CountChildren(mesh)
g = GetChild(mesh, i)
EnumerateChildren% g, store%, 0
Next
;return number of children
Return numc%
End Function
;-----------------------------------------------------------------------------------------------------
;
I've used this method:
(1) parse file, search all parents for the vertices and the amount/weight
(2) place a pivot on each vertex for every parent it uses and connect it to this parent, thus creating several "versions" of each vertex.
(3) on runtime, calculate the average position between each version of the vertex, taking in account their weights.