Hi everyone i’ve just finished my biped exporter for my game and i thought there may be other 3ds max users who will probably found this tool useful.
So basically what it does is searches the scene and exports the FIRST biped found in the scene hierarchy.
It was tested with 3ds max 9 but should work with any version… let me know if you found some issues…
NOTE : Make sure your biped and the skined mesh’s biped have the axact same size otherwise the exported data will be invalid (but the result should be pretty funny long hands , legs etc)
I had the same issue with irrlicht as the bone positions changing in different biped sizes.I solved this by exporting the distance between the root node and the first spine bone.
and calculate the scale between mesh and biped
and by multiplying the positions with this value corrected the issue , although i don’t know how this should be done in Urho3D…
There’s no option to add attachments so i just paste it here… copy , create new script, and run it
-- counts all (maximum) frames in the biped.
fn countFramesInBiped theBiped =
(
retFrames = 0
for c = 1 to 22 do
(
for l = 1 to 4 do
(
bod = biped.getNode theBiped c link:l
if bod != undefined then
(
if bod.controller.keys.count > 0 then
(
lastKey = bod.controller.keys[bod.controller.keys.count]
if lastKey.time > retFrames then retFrames = lastKey.time
)
)
)
)
retFrames
)
-- returns bone count
fn countBonesInBiped theBiped =
(
retBones = 0
for c = 1 to 22 do
(
-- these are the com object so ignore it... we don't want to export them 3x times
if c == 14 or c == 15 or c == 16 then continue
for l = 1 to 4 do
(
bod = biped.getNode theBiped c link:l
if bod != undefined then
(
retBones += 1
)
)
)
retBones
)
-- Generates standard names for bones.Replaces spaces with _ (Bip01 Head = Bip01_Head)
fn generateStandardName theString =
(
nArr = filterString theString " "
finString = ""
for z = 1 to nArr.count do
(
finString += (nArr[z] + "_")
)
f = (substring finString 1 (finString.count-1))
f
)
/*
byte[4] Identifier "UANI"
cstring Animation name
float Length in seconds
uint Number of tracks
For each track:
cstring Track name (practically same as the bone name that should be driven)
byte Mask of included animation data. 1 = bone positions 2 = bone rotations 4 = bone scaling
uint Number of keyframes
For each keyframe:
float Time position in seconds
Vector3 Position (if included in data)
Quaternion Rotation (if included in data)
Vector3 Scale (if included in data)
*/
fn inf_ExportBipedAnim theFile animName=
(
-- find biped in the scene
for z = 1 to objects.count do
(
if objects[z].parent == undefined and classof objects[z] == Biped_Object then
(
-- We have our Biped COM object
theBiped = objects[z] -- points to com object
-- calculate frame count
frameCount = countFramesInBiped theBiped
magic = "UANI"
for x = 1 to magic.count do
(
writeByte theFile (bit.charAsInt magic[x])
)
writeString theFile animName -- animation name
-- Only keyframe per frame is supported... so the length is equal to keyframes
-- keysframes starting from 0 and not 1
writeFloat theFile (frameCount + 1)
boneCount = countBonesInBiped theBiped
writeLong theFile boneCount -- number of tracks
print
print (" Number of frames = " + frameCount as string)
print (" Number of bones = " + boneCount as string)
-- export frames :
for a = 1 to 22 do
(
-- these are all the com object so ignore them
if a == 14 or a == 15 or a == 16 then continue
for b = 1 to 4 do
(
bod = biped.getNode theBiped a link:b
if bod != undefined then
(
-- we have a valid bone , so export its data
-- write bone name
st = generateStandardName bod.name
writeString theFile st
print ("Exporting Bone : " + st)
writeByte theFile 3 -- mask : pos and rotate scale is ignored
writeLong theFile (frameCount+1) -- keyframes count
for fr = 0 to frameCount do
(
at time (fr)
(
-- claculate local transform for each body
transf = bod.transform
if bod.parent != undefined then transf = bod.transform * (inverse bod.parent.transform)
writeFloat theFile fr
writeFloat theFile transf.pos.x
writeFloat theFile transf.pos.z
writeFloat theFile transf.pos.y
writeFloat theFile transf.rotation.w
writeFloat theFile transf.rotation.x
writeFloat theFile transf.rotation.z
writeFloat theFile transf.rotation.y
)-- endof at time()
)-- endof frame count loop
) -- body != undefined
)-- for b = 1 to 4
) -- for a = 1 to 22
) -- if objects[z].parent == undefined and classof objects[z] == Biped_Object
) -- scene objects loop
)
rollout unnamedRollout "Urho3D Biped anim exporter 0.1" width:482 height:160
(
label lbl1 "Urho3D Biped animation exporter." pos:[155,9] width:166 height:19
label lbl2 "The script will automatically export the FIRST biped found in the scene ! Make sure your animated biped and the skined mesh's biped are the exact same size !" pos:[11,44] width:426 height:34
button btn_Export "Export" pos:[363,121] width:80 height:23
on btn_Export pressed do
(
fname = getSaveFileName caption:"Save As.." types:"*.ani|*.ani"
if fname != undefined then
(
fr = fopen fname "wb"
inf_ExportBipedAnim fr (getFilenameFile fname)
fclose fr
)
)
)
createDialog unnamedRollout